代码之家  ›  专栏  ›  技术社区  ›  Yaroslav Bulatov

Mathematica中近似相等检验的算子

  •  3
  • Yaroslav Bulatov  · 技术社区  · 14 年前

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

    处理这样的案子 TildeTilde 工作方式 Equal 但它不会检查符号相等性,而是将未知值替换为数值,并在多个点检查数值相等性。

    未知数是表达式中看起来像变量的东西。我能想到的那些 x , x[1,2] Subscript[x,2,3] . 任何提示欢迎!

    编辑

    通常我会做如下的事情,但它需要指定变量,有时需要更改Chop公差,“10个样本”似乎是任意的。一个理想的测试仪应该是一个工作类似 Equals 保证有意义 False 答案。(补充 等于 有意义的 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 回复  |  直到 14 年前
        1
  •  6
  •   Michael Pilat    14 年前

    如果您使用 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 /等选择 查找最大值 . 你也可以重复 查找最大值 对于变量的多个起点。

    作为旁白,请注意 TildeTilde ,(即。 ~~ ),是的中缀运算符 StringExpression .

    啊!

        2
  •  1
  •   Janus    14 年前

    我真的认为为要替换的符号指定模式和范围是值得的。下面的代码是我已经使用了一段时间的等式测试生成器的精良版本。
    我的看法是 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