Conversation
|
Looks like there's some assumption being made that for a sliced mps e.g. |
|
Re the sliced MPS, seems the assumption is setting/getting a unit range function deepcopy_ortho_center(M::AbstractMPS)
M = copy(M)
c = ortho_lims(M)
# TODO: define `getindex(::AbstractMPS, I)` to return `AbstractMPS`
M[c] = deepcopy(typeof(M)(M[c]))
return M
endWhat are your thoughts given the TODO Matt? |
|
I think slicing an MPS/MPO with a unit range should return an MPS/MPO, if we make that change we can just update other code like the one you quote accordingly. However, the definition in |
|
Just pushed a hopefully better performance version of julia> eigvals(array(A,i,i'))
2-element Vector{Float64}:
0.031100580805835387
1.5475689615743486
julia> sqrt(Hermitian(array(A,i,i'))) ≈ array(sqrt(A),i,i')
true
julia> eigvals(array(B,i,i'))
2-element Vector{Float64}:
-0.9688994191941646
0.5475689615743488
jjulia> sqrt(array(B,i,i'))
2×2 Matrix{ComplexF64}:
0.638411+0.135107im 0.254641-0.338726im
0.254641-0.338726im 0.101568+0.84922im
julia> sqrt(B)
ERROR: DomainError with -0.9688994191941646:
sqrt was called with a negative real argument but will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).
Stacktrace:
[1] throw_complex_domainerror(f::Symbol, x::Float64)
@ Base.Math ./math.jl:33
[2] sqrt
@ ./math.jl:608 [inlined]
... |
|
@mtfishman now that ITensorMPS is out of ITensors I think this PR is complete pending your review and I'll move over there to fix the slice issue |
| # return itensor(sqrt(tensor(T))) | ||
| #end | ||
| D, U = eigen(T; ishermitian=ishermitian) | ||
| sqrtD = map_diag(x -> x < 0 && abs(x) < atol ? 0 : sqrt(x), D) |
There was a problem hiding this comment.
| sqrtD = map_diag(x -> x < 0 && abs(x) < atol ? 0 : sqrt(x), D) | |
| sqrtD = map_diag(x -> x < 0 && abs(x) < atol ? zero(real(eltype(T)) : sqrt(x), D) |
Additionally, I agree with your comment above that for large negative values we should convert to complex.
|
Thanks, I implemented all of those suggested changes. Do you have any suggestions on how to handle the complex conversion? It seems that A = random_itensor(i,i')
ITensors.NDTensors.map_diag(x-> x+1.0im, A)crashes (Theoretically this could be on the user but that seems a bit annoying) |
|
Looks like |
|
It's a bit hacky, but one strategy could be be to change # Should go in `NDTensors.Exposed`, and specialized definitions may need to be added
# for certain GPU backends.
LinearAlgebra.copy_oftype(exposed_t::Exposed, elt::Type) = LinearAlgebra.copy_oftype(unexpose(exposed_t), elt)
function map_diag(f::Function, exposed_t::Exposed)
new_elt = Base._return_type(f, Tuple{eltype(exposed_t)})
t_dest = LinearAlgebra.copy_oftype(exposed_t, new_elt)
map_diag!(f, expose(t_dest), exposed_t)
return t_dest
end |
|
Thanks Matt, it seems that I'm not familiar enough with the NDTensors internals to determine what should be changed. That snippet doesn't seem to work as it gets a call to |
This PR adds a few of the functions living in https://github.com/ITensor/ITensorInfiniteMPS.jl/blob/main/src/ITensors.jl
The one thing missing at the moment is the more efficient
sqrt(T::DiagTensor)which I couldn't get working, but the eigen implementation seems sane at the moment so there may be no need