Mathematica中近似等式测试的运算符

时间:2010-11-17 03:55:51

标签: wolfram-mathematica

我经常需要检查是否expr1==expr2,检查符号相等是否很难,但数字检查就足够了

为了处理这种情况,让TildeTildeEqual一样工作是很好的,但不是检查符号相等,而是用数值替换未知数,并在几个点检查数字相等。

未知数是表达式中“看起来像”变量的东西。我能想到的是xx[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算法进行此类等式测试

2 个答案:

答案 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(链接直接可浏览的代码)。

主要特点:

  • 使用Michael的深度优先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
相关问题