我经常需要检查是否expr1==expr2
,检查符号相等是否很难,但数字检查就足够了
为了处理这种情况,让TildeTilde
像Equal
一样工作是很好的,但不是检查符号相等,而是用数值替换未知数,并在几个点检查数字相等。
未知数是表达式中“看起来像”变量的东西。我能想到的是x
,x[1,2]
和Subscript[x,2,3]
。欢迎任何提示!
修改
通常我会做类似下面的事情,但它需要指定变量,有时需要更改Chop容差,而“10个样本”似乎是任意的。理想的测试人员将是一个像Equals
一样工作的函数,并保证有意义的False
答案。 (以补充Equals
具有有意义的True
答案)
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使用this算法进行此类等式测试
答案 0 :(得分:6)
如果您使用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
显然,一般情况下,这可能会遇到各种数字错误问题,您可以使用AccuracyGoal
/ PrecisionGoal
/ WorkingPrecision
/等选项来解决FindMaximum
。您还可以为变量的多个起点重复FindMaximum
。
顺便说一句,请注意TildeTilde
(即~~
)是StringExpression
的中缀运算符。
HTH!
答案 1 :(得分:1)
我真的认为指定要替换的符号的模式和范围是值得的。下面的代码是我使用了一段时间的相等测试生成器的抛光版本
我对此的看法是让numEqual=MakeEqualityTest[...]
生成一个相等的测试,然后您可以应用于lhs ~numEqual~rhs
或您喜欢的任何内容。你的问题是一个很好的机会来完善我的一些代码,最后它太大了,不适合这里,所以我把它放在github(链接直接可浏览的代码)。
主要特点:
Cases
技巧获得合理的自动模式Norm[#1-#2]&
作为距离测试来处理向量,矩阵等。使用示例:
numeq=MakeEqualityTester[];
(Cos[x]^2+Sin[x]^2)~numeq~1
Sqrt[x^2]~numeq~x
Out[5]= True
During evaluation of In[4]:= EqualityTest::notEqual: The expressions Sqrt[x^2] and x were not equal at the following point:
Out[6]= {x->-0.352399}
您也可以通过效用函数直接致电:
EqualityTest[1,Cos[x]^2+Sin[x]^2]
Out[7]= True
以下是特殊符号和分布的示例:
poseq=MakeEqualityTester[{
Subscript[y,_]:>RandomReal[{10,11}],
Automatic
},Tolerance-> 10^(-5)];
x ~poseq~ Sqrt[x^2]
Subscript[y,1] ~poseq~ Sqrt[Subscript[y,1]^2]
During evaluation of In[18]:= EqualityTest::notEqual: The expressions x and Sqrt[x^2] were not equal at the following point:
Out[19]= {x->-0.272029}
Out[20]= True