在 Julia 中断言对角化向量时,是什么导致了“AssertionError”?

Pål*_*tan 2 assertion julia

我一直在 julia做一些练习,我目前正在尝试将@assert一个向量对角化为一个矩阵,与练习笔记本中给出的“解矩阵”相对。但是,AssertionError在针对提供的解决方案断言我的代码时,我得到了一个。我的代码示例:

julia> using LinearAlgebra

julia> A =
[
 140   97   74  168  131
  97  106   89  131   36
  74   89  152  144   71
 168  131  144   54  142
 131   36   71  142   36
]

5×5 Matrix{Int64}:
 140   97   74  168  131
  97  106   89  131   36
  74   89  152  144   71
 168  131  144   54  142
 131   36   71  142   36

julia> A_eigv = eigen(A).values

5-element Vector{Float64}:
 -128.49322764802145
  -55.887784553057
   42.752167279318854
   87.16111477514494
  542.4677301466137

julia> A_diag = Diagonal(A_eigv)

5×5 Diagonal{Float64, Vector{Float64}}:
 -128.493     ?        ?        ?         ? 
     ?     -55.8878    ?        ?         ? 
     ?        ?      42.7522    ?         ? 
     ?        ?        ?      87.1611     ? 
     ?        ?        ?        ?      542.468

julia> @assert A_diag ==  [-128.493    0.0      0.0      0.0       0.0;
    0.0    -55.8878   0.0      0.0       0.0;
    0.0      0.0     42.7522   0.0       0.0;
    0.0      0.0      0.0     87.1611    0.0;
    0.0 0.0      0.0      0.0     542.468]

AssertionError: A_diag == [-128.493 0.0 0.0 0.0 0.0; 0.0 -55.8878 0.0 0.0 0.0; 0.0 0.0 42.7522 0.0 0.0; 0.0 0.0 0.0 87.1611 0.0; 0.0 0.0 0.0 0.0 542.468]

Stacktrace:
 [1] top-level scope
   @ In[90]:1
 [2] eval
   @ ./boot.jl:360 [inlined]
 [3] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
   @ Base ./loading.jl:1094
Run Code Online (Sandbox Code Playgroud)

我最初的假设是小数位数的差异是导致错误的原因。因此我==?\approx)代替。但是,如下面的代码示例所示,错误仍然存​​在:

julia> @assert A_diag ? #\approx
[-128.493    0.0      0.0      0.0       0.0;
    0.0    -55.8878   0.0      0.0       0.0;
    0.0      0.0     42.7522   0.0       0.0;
    0.0      0.0      0.0     87.1611    0.0;
    0.0 0.0      0.0      0.0     542.468]

AssertionError: A_diag ? [-128.493 0.0 0.0 0.0 0.0; 0.0 -55.8878 0.0 0.0 0.0; 0.0 0.0 42.7522 0.0 0.0; 0.0 0.0 0.0 87.1611 0.0; 0.0 0.0 0.0 0.0 542.468]

Stacktrace:
 [1] top-level scope
   @ In[97]:1
 [2] eval
   @ ./boot.jl:360 [inlined]
 [3] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
   @ Base ./loading.jl:1094

Run Code Online (Sandbox Code Playgroud)

我已经多次阅读我的代码,我不知所措。我的对角矩阵 ( A_diag) 中的值似乎与解矩阵相同。此外,将语句设置为近似等于 ( \approx) 会呈现相同的错误,因此我假设我可以计算出十进制错误。

我的主要问题是:是什么导致了AssertionError

Bal*_*Ben 5

不,为了测试相等性,这些点被视为 0。

julia> Diagonal(1:2) == [1 0; 0 2]
true
Run Code Online (Sandbox Code Playgroud)

你的问题是你的数组实际上相等;-128.49322764802145不一样-128.493。(数组的漂亮打印版本会截断浮点数以进行显示,但这不是真正的底层值!)。

[编辑:]

在这种情况下,使用?( \approx) 也会失败。原因在文档中解释isapprox()

二元运算符?等效于isapprox使用默认参数,

如果atol > 0未指定an ,则rtol默认为xor类型的 eps 的平方根y,以较大者为准(最不精确)。

本质上,这意味着?将测试近似相等性,?eps()其相对容差大约等于 1.5e-8 或 0.0000015%。这个容差太低了,增加容差将解决问题。例如:

# Option 1: Absolute tolerance. Set to a reasonable max deviation:
julia> isapprox(A_diag, sol_mat, atol = 1e-3)
true

# Option 2: Relative tolerance. Setting rtol = 1e-n, n is the number of significant digits in either matrices will work in most cases.
julia> isapprox(A_diag, sol_mat, rtol = 1e-6)
true
Run Code Online (Sandbox Code Playgroud)

由于解矩阵提供六位有效数字的值,另一种替代方法是将值四舍五入A_diag到这个数字 og 数字并测试是否相等。例如:

julia> round.(A_diag, RoundNearestTiesUp, sigdigits=6) == 
[-128.493    0.0      0.0      0.0       0.0;
    0.0    -55.8878   0.0      0.0       0.0;
    0.0      0.0     42.7522   0.0       0.0;
    0.0      0.0      0.0     87.1611    0.0;
    0.0      0.0      0.0      0.0     542.468]
true
Run Code Online (Sandbox Code Playgroud)

  • @PålBjartan 您还必须设置大约 s 的容差 (2认同)