2011-03-25 24 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)是一種不好的做法,應該避免。首先,上面的解決方案可能不健壯,並且您可能會發現自己添加了更多規則以使其在所有情況下都能正常工作。另外,通常情況下,最好避免重新定義內置函數(如果可以的話)(原因之一是這樣做可能會導致一些非常微妙的錯誤,因爲其他一些系統函數可能會使用您重新定義的錯誤,並且您無法控制超過它)。我會實現我自己的差異化功能。這不是集成,它是相對簡單的做法,並且不會讓其他系統的功能處於危險之中。

相關問題