2011-03-25 22 views
3

我想实现一个运算符f,这个运算符可以区分D如何定义在Mathematica中通过D的函数

Unprotect[D]; 
D[f[y___], x] := f[D[y, x]]; 
Protect[D]; 

D[f[Sin[x]], x] 
D[f[Sin[x]] + 1, x] 

不幸的是这个代码产生两个不同的结果

f[Cos[x]] (* as expected *) 
Cos[x] f´[Sin[x]] (* cannot explain *) 

我想知道,这是怎么回事,以及如何解决的替换规则,使得第二表达式求f[Cos[x]]为好。

更新。解决方案1 ​​以下解决方案似乎可以完成重新定义D运算符的工作(尽管我无法完全理解我自己的代码)。

PartialDerivative[x_, x_] := 1; 

PartialDerivative[c_, x_] := 0 /; FreeQ[c, x]; 

PartialDerivative[f_ConditionalExpectation, x_] := 
    ConditionalExpectation[PartialDerivative[f, x]]; 

PartialDerivative[(f_)[g__], x_] := Module[{i, n, p}, 
     n = Length[SequenceHold[g]]; 
     Sum[ 
      p = ConstantArray[0, n]; p[[i]] = 1; 
      ((Derivative[##1][f] &) @@ p)[g]* 
       PartialDerivative[SequenceHold[g][[i]], x], {i, 1, n}]]; 

如果有更有经验的人可以看看代码并告诉我这种方法是否正确,我将不胜感激。

回答

7

模式符合语法,而不是语义。对于内置函数,如果您重新定义它们,并且您的模式不匹配,则使用内置规则(定义)。要查看模式是否匹配或为何不匹配,FullForm通常很有用。通过这种方式,我们可以看到:当你有f

In[26]:= FullForm[HoldForm[D[f[Sin[x]]+1,x]]] 
Out[26]//FullForm= HoldForm[D[Plus[f[Sin[x]],1],x]] 

你的定义是唯一有效的[_]内D,而在这里你有D[Plus[f[..],1],x]。因此,您的定义不匹配,然后使用内置。这里有一种方法可以扩展它来覆盖这种情况:

Unprotect[D]; 
D[f[y___], x_] := f[D[y, x]]; 
D[HoldPattern[Plus[left___, a_f, right___]], x_] := 
    D[Plus[left], x] + D[a, x] + D[Plus[right], x]; 
Protect[D]; 

现在它会按预期工作。但是请注意,IMO以这种方式重新定义内置函数(如D)是一种不好的做法,应该避免。首先,上面的解决方案可能不健壮,并且您可能会发现自己添加了更多规则以使其在所有情况下都能正常工作。另外,通常情况下,最好避免重新定义内置函数(如果可以的话)(原因之一是这样做可能会导致一些非常微妙的错误,因为其他一些系统函数可能会使用您重新定义的错误,并且您无法控制超过它)。我会实现我自己的差异化功能。这不是集成,它是相对简单的做法,并且不会让其他系统的功能处于危险之中。

相关问题