Question regarding sparse vector

What am I doing wrong here:

using SparseArrays
v = sparsevec([1, 2, 3], [1.0, 0.0, 1.0])
println("iter")
for x in v println(x); end
println("map")
map(x -> begin println(x); x; end, v)
println("end")

yielding

iter
1.0
0.0
1.0
map
0.0
1.0
0.0
1.0
end

You mean because of the additional 0.0 in the map? I think that is because the function to be mapped is called once before the actual mapping, probably to infer the type of the output.

iteration goes over the non-trivial values you have in the sparse matrix, map will see the entire matrix, where the empty parts are just assumed zero. (by definition of sparse matrix…)

Not the type, but to check whether f(0) = 0.

2 Likes

But that specifically (at least) for sparse arrays. I was deleting the post because that does not happen with standard vectors.

julia> v = [1.0, 2.0, 3.0]
3-element Vector{Float64}:
 1.0
 2.0
 3.0

julia> map(x -> println(x), v)
1.0
2.0
3.0
3-element Vector{Nothing}:
 nothing
 nothing
 nothing

julia> v = sparsevec([1, 2, 3], [1.0, 2.0, 3.0])
3-element SparseVector{Float64, Int64} with 3 stored entries:
  [1]  =  1.0
  [2]  =  2.0
  [3]  =  3.0

julia> map(x -> println(x), v)
0.0
1.0
2.0
3.0
3-element SparseVector{Nothing, Int64} with 3 stored entries:
  [1]  =  nothing
  [2]  =  nothing
  [3]  =  nothing


Sorry for the confusion, so the function given to map definitely has to be pure. Any reference where to find map for sparse vectors in the repository (I did have a quick look into https://github.com/JuliaLang/julia/blob/c646b5d4893e45a413705d3fea0a7227c4fe7aae/stdlib/SparseArrays/src/sparsevector.jl)?

BTW is there any reason, why the iteration doesn’t return pairs of (index, value) for non-zero values?

Is something like this what you want?

julia> v = sparsevec([1, 2, 5], [1.0, 2.0, 3.0]);

julia> map(i -> (i,sin(v[i])), v.nzind)
3-element Vector{Tuple{Int64, Float64}}:
 (1, 0.8414709848078965)
 (2, 0.9092974268256817)
 (5, 0.1411200080598672)
1 Like

Nice! I missed that the original slack discussion is continuing here.

I suspect you are right. Any hint how to verify? Thanks!

SparseArrays/src/higherorderfns.jl#L165-L166 for example.


FYI, very easy to figure out with Debugger.jl: (add breakpoint at f, c to continue to breakpoint, f 2 to step up the call chain and you end up with the lines I linked above):

julia> using SparseArrays, Debugger                                                                                                                                                  
                                                                                                                                                                                     
julia> f(x) = 0;                                                                                                                                                                     
                                                                                                                                                                                     
julia> v = sparsevec([1, 2, 5], [1.0, 2.0, 3.0]);                                                                                                                                    
                                                                                                                                                                                     
julia> @enter map(f, v)                                                                                                                                                              
In map(f, A) at /Users/fredrik/julia-master/usr/share/julia/stdlib/v1.8/SparseArrays/src/higherorderfns.jl:148                                                                       
>148  map(f::Tf, A::SparseVector) where {Tf} = _noshapecheck_map(f, A)                                                                                                               
                                                                                                                                                                                     
About to run: (SparseArrays.HigherOrderFns._noshapecheck_map)(f,   [1]  =  1.0
  [2]  =  2.0
  [5]  =  3.0)
1|debug> bp add f
[ Info: added breakpoint for function f
1] f

1|debug> c
Hit breakpoint:
In f(x) at REPL[14]:1
>1  1 ─     return 0

About to run: return 0
1|debug> f 2
In _noshapecheck_map(f, A, Bs) at /Users/fredrik/julia-master/usr/share/julia/stdlib/v1.8/SparseArrays/src/higherorderfns.jl:164
 164  function _noshapecheck_map(f::Tf, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N}) where {Tf,N}
>165      fofzeros = f(_zeros_eltypes(A, Bs...)...)
 166      fpreszeros = _iszero(fofzeros)
 167      maxnnzC = Int(fpreszeros ? min(widelength(A), _sumnnzs(A, Bs...)) : widelength(A))
 168      entrytypeC = Base.Broadcast.combine_eltypes(f, (A, Bs...))
 169      indextypeC = _promote_indtype(A, Bs...)
 170      C = _allocres(size(A), indextypeC, entrytypeC, maxnnzC)
 171      return fpreszeros ? _map_zeropres!(f, C, A, Bs...) :
 172                          _map_notzeropres!(f, fofzeros, C, A, Bs...)
 173  end

3 Likes

Thanks a lot!