我经常需要检查expr1==expr2 ,检查符号相等是否很难,但数字检查就足够了
为了处理这种情况,让TildeTilde像Equal TildeTilde工作是TildeTilde但不是检查符号相等,而是用数值替换未知数,并在几个点检查数字相等。
未知数是表达式中“看起来像”变量的东西。 我能想到的有x , x[1,2]和下Subscript[x,2,3] 。 欢迎任何提示!
编辑
通常我会做类似下面的事情,但它需要指定变量,有时需要改变Chop容差,“10个样本”似乎是任意的。 一个理想的测试者将是一个像Equals一样工作的函数,并保证有意义的False答案。 (补充具有有意义的True答案的Equals )
approxEqual[expr1_, expr2_, vars_] := Chop[(expr1 - expr2 /. Thread[vars -> #]) & /@ RandomReal[{-1, 1}, {10, Length[vars]}]] == Table[0, {10}]; expr1 = 1/Sqrt[2] Log[Cosh[q + x/Sqrt[2]] Sech[q - x/Sqrt[2]]]; expr2 = Sqrt[2] ArcTanh[Tanh[q] Tanh[x/Sqrt[2]]]; approxEqual[expr1, expr2, {q, x}]作为旁注,显然Maple使用此算法进行此类相等测试
I often need to check if expr1==expr2, where checking for symbolic equality is hard, but a numeric check suffices
To deal with such cases it would be neat to have TildeTilde work like Equal but instead of checking symbolic equality it would substitute unknowns with numeric values and check for numeric equality at several points.
Unknowns are things that "look like" variables in the expression. The ones I can think of have form x,x[1,2] and Subscript[x,2,3]. Any tips welcome!
edit
usually I do something like below, but it requires specifying variables, sometimes requires changing Chop tolerance, and "10 samples" seems arbitrary. An ideal tester would be a function that works like Equals and guarantees meaningful False answers. (to complement Equals which has meaningful True answers)
approxEqual[expr1_, expr2_, vars_] := Chop[(expr1 - expr2 /. Thread[vars -> #]) & /@ RandomReal[{-1, 1}, {10, Length[vars]}]] == Table[0, {10}]; expr1 = 1/Sqrt[2] Log[Cosh[q + x/Sqrt[2]] Sech[q - x/Sqrt[2]]]; expr2 = Sqrt[2] ArcTanh[Tanh[q] Tanh[x/Sqrt[2]]]; approxEqual[expr1, expr2, {q, x}]As a side-note, apparently Maple uses this algorithm for such equality testing
最满意答案
如果您使用FindMaximum作为FindMaximum ,这有点简单:
In[64]:= FindMaximum[expr1 - expr2, q, x] During evaluation of In[64]:= FindMaximum::fmgz: Encountered a gradient that is effectively zero. The result returned may not be a maximum; it may be a minimum or a saddle point. >> Out[64]= {1.11022*10^-16, {q -> 1., x -> 1.}}从而:
approxEqual[lhs_, rhs_, tol_: 10^-10] := Module[{vars}, vars = DeleteDuplicates[ Cases[{lhs,rhs}, s_Symbol /; Not[ValueQ[s]], Infinity] ]; Chop[ First[ Quiet[FindMaximum[Abs[lhs - rhs], Evaluate[Sequence @@ vars]]] ], tol] == 0 ] In[65]:= approxEqual[expr1, expr2] Out[65]= True In[66]:= approxEqual[expr1, expr2, 10^-20] Out[66]= False显然,一般情况下,这可能会遇到各种数值错误问题,您可以使用WorkingPrecision AccuracyGoal / PrecisionGoal / WorkingPrecision /等选项来FindMaximum 。 您还可FindMaximum变量的多个起点重复FindMaximum 。
另外,请注意TildeTilde (即~~ )是StringExpression的中缀运算符。
HTH!
This is somewhat straightforward if you use FindMaximum as a jumping-off point:
In[64]:= FindMaximum[expr1 - expr2, q, x] During evaluation of In[64]:= FindMaximum::fmgz: Encountered a gradient that is effectively zero. The result returned may not be a maximum; it may be a minimum or a saddle point. >> Out[64]= {1.11022*10^-16, {q -> 1., x -> 1.}}Thus:
approxEqual[lhs_, rhs_, tol_: 10^-10] := Module[{vars}, vars = DeleteDuplicates[ Cases[{lhs,rhs}, s_Symbol /; Not[ValueQ[s]], Infinity] ]; Chop[ First[ Quiet[FindMaximum[Abs[lhs - rhs], Evaluate[Sequence @@ vars]]] ], tol] == 0 ] In[65]:= approxEqual[expr1, expr2] Out[65]= True In[66]:= approxEqual[expr1, expr2, 10^-20] Out[66]= FalseObviously, in general this is subject to various numerical error issues that you can address with AccuracyGoal / PrecisionGoal / WorkingPrecision / etc. options to FindMaximum. You could also repeat FindMaximum for multiple starting points for the variables.
As an aside, note that TildeTilde, (i.e. ~~), is the infix operator for StringExpression.
HTH!
更多推荐
发布评论