Sparse and Structured Array Utilities

Sparse Constructors

In addition to the Tensor constructor, Finch provides a number of convenience constructors for common tensor types. For example, the spzeros and sprand functions have fspzeros and fsprand counterparts that return Finch tensors. We can also construct a sparse COO Tensor from a list of indices and values using the fsparse function.

Finch.fsparseFunction
fsparse(I::Tuple, V,[ M::Tuple, combine])

Create a sparse COO tensor S such that size(S) == M and S[(i[q] for i = I)...] = V[q]. The combine function is used to combine duplicates. If M is not specified, it is set to map(maximum, I). If the combine function is not supplied, combine defaults to + unless the elements of V are Booleans in which case combine defaults to |. All elements of I must satisfy 1 <= I[n][q] <= M[n]. Numerical zeros are retained as structural nonzeros; to drop numerical zeros, use dropzeros!.

See also: sparse

Examples

julia> I = ( [1, 2, 3], [1, 2, 3], [1, 2, 3]);

julia> V = [1.0; 2.0; 3.0];

julia> fsparse(I, V) SparseCOO (0.0) [1:3×1:3×1:3] │ │ │ └─└─└─[1, 1, 1] [2, 2, 2] [3, 3, 3] 1.0 2.0 3.0

Finch.fsparse!Function
fsparse!(I..., V,[ M::Tuple])

Like fsparse, but the coordinates must be sorted and unique, and memory is reused.

Finch.fsprandFunction
fsprand([rng],[type], M..., p, [rfn])

Create a random sparse tensor of size m in COO format. There are two cases: - If p is floating point, the probability of any element being nonzero is independently given by p (and hence the expected density of nonzeros is also p). - If p is an integer, exactly p nonzeros are distributed uniformly at random throughout the tensor (and hence the density of nonzeros is exactly p / prod(M)). Nonzero values are sampled from the distribution specified by rfn and have the type type. The uniform distribution is used in case rfn is not specified. The optional rng argument specifies a random number generator.

See also: (sprand)(https://docs.julialang.org/en/v1/stdlib/SparseArrays/#SparseArrays.sprand)

Examples

julia> fsprand(Bool, 3, 3, 0.5)
SparseCOO (false) [1:3,1:3]
├─├─[1, 1]: true
├─├─[3, 1]: true
├─├─[2, 2]: true
├─├─[3, 2]: true
├─├─[3, 3]: true

julia> fsprand(Float64, 2, 2, 2, 0.5)
SparseCOO (0.0) [1:2,1:2,1:2]
├─├─├─[2, 2, 1]: 0.6478553157718558
├─├─├─[1, 1, 2]: 0.996665291437684
├─├─├─[2, 1, 2]: 0.7491940599574348
Finch.fspzerosFunction
fspzeros([type], M::Tuple)

Create a random zero tensor of size M, with elements of type type. The tensor is in COO format.

See also: (spzeros)(https://docs.julialang.org/en/v1/stdlib/SparseArrays/#SparseArrays.spzeros)

Examples

julia> fspzeros(Bool, 3, 3)
SparseCOO{2} (false) [:,1:3]

julia> fspzeros(Float64, 2, 2, 2)
SparseCOO{3} (0.0) [:,:,1:2]
Finch.ffindnzFunction
ffindnz(arr)

Return the nonzero elements of arr, as Finch understands arr. Returns (I..., V), where I are the coordinate vectors, one for each mode of arr, and V is a vector of corresponding nonzero values, which can be passed to fsparse.

See also: (findnz)(https://docs.julialang.org/en/v1/stdlib/SparseArrays/#SparseArrays.findnz)

Fill Values

Finch tensors support an arbitrary "background" value for sparse arrays. While most arrays use 0 as the background value, this is not always the case. For example, a sparse array of Int might use typemin(Int) as the background value. The default function returns the background value of a tensor. If you ever want to change the background value of an existing array, you can use the redefault! function. The countstored function returns the number of stored elements in a tensor, and calling pattern! on a tensor returns tensor which is true whereever the original tensor stores a value. Note that countstored doesn't always return the number of non-zero elements in a tensor, as it counts the number of stored elements, and stored elements may include the background value. You can call dropdefaults! to remove explicitly stored background values from a tensor.

julia> A = fsparse([1, 1, 2, 3], [2, 4, 5, 6], [1.0, 2.0, 3.0])
SparseCOO{2} (0.0) [:,1:6]
├─ [1, 2]: 1.0
├─ [1, 4]: 2.0
└─ [2, 5]: 3.0

julia> min.(A, -1)
Dense [:,1:6]
├─ [:, 1]: Dense [1:3]
│  ├─ [1]: -1.0
│  ├─ [2]: -1.0
│  └─ [3]: -1.0
├─ [:, 2]: Dense [1:3]
│  ├─ [1]: -1.0
│  ├─ [2]: -1.0
│  └─ [3]: -1.0
├─ [:, 3]: Dense [1:3]
│  ├─ [1]: -1.0
│  ├─ [2]: -1.0
│  └─ [3]: -1.0
├─ [:, 4]: Dense [1:3]
│  ├─ [1]: -1.0
│  ├─ [2]: -1.0
│  └─ [3]: -1.0
├─ [:, 5]: Dense [1:3]
│  ├─ [1]: -1.0
│  ├─ [2]: -1.0
│  └─ [3]: -1.0
└─ [:, 6]: Dense [1:3]
   ├─ [1]: -1.0
   ├─ [2]: -1.0
   └─ [3]: -1.0

julia> default(A)
0.0

julia> B = redefault!(A, -Inf)
SparseCOO{2} (-Inf) [:,1:6]
├─ [1, 2]: 1.0
├─ [1, 4]: 2.0
└─ [2, 5]: 3.0

julia> min.(B, -1)
Sparse (-Inf) [:,1:6]
├─ [:, 2]: Sparse (-Inf) [1:3]
│  └─ [1]: -1.0
├─ [:, 4]: Sparse (-Inf) [1:3]
│  └─ [1]: -1.0
└─ [:, 5]: Sparse (-Inf) [1:3]
   └─ [2]: -1.0

julia> countstored(A)
3

julia> pattern!(A)
SparseCOO{2} (false) [:,1:6]
├─ [1, 2]: true
├─ [1, 4]: true
└─ [2, 5]: true
Finch.redefault!Function
redefault!(fbr, init)

Return a tensor which is equal to fbr, but with the default (implicit) value set to init. May reuse memory and render the original tensor unusable when modified.

julia> A = Tensor(SparseList(Element(0.0), 10), [2.0, 0.0, 3.0, 0.0, 4.0, 0.0, 5.0, 0.0, 6.0, 0.0])
SparseList (0.0) [1:10]
├─ [1]: 2.0
├─ [3]: 3.0
├─ [5]: 4.0
├─ [7]: 5.0
└─ [9]: 6.0

julia> redefault!(A, Inf)
SparseList (Inf) [1:10]
├─ [1]: 2.0
├─ [3]: 3.0
├─ [5]: 4.0
├─ [7]: 5.0
└─ [9]: 6.0
Finch.pattern!Function
pattern!(fbr)

Return the pattern of fbr. That is, return a tensor which is true wherever fbr is structurally unequal to it's default. May reuse memory and render the original tensor unusable when modified.

julia> A = Tensor(SparseList(Element(0.0), 10), [2.0, 0.0, 3.0, 0.0, 4.0, 0.0, 5.0, 0.0, 6.0, 0.0])
SparseList (0.0) [1:10]
├─ [1]: 2.0
├─ [3]: 3.0
├─ [5]: 4.0
├─ [7]: 5.0
└─ [9]: 6.0

julia> pattern!(A)
SparseList (false) [1:10]
├─ [1]: true
├─ [3]: true
├─ [5]: true
├─ [7]: true
└─ [9]: true
Finch.countstoredFunction
countstored(arr)

Return the number of stored elements in arr. If there are explicitly stored default elements, they are counted too.

See also: (SparseArrays.nnz)(https://docs.julialang.org/en/v1/stdlib/SparseArrays/#SparseArrays.nnz) and (Base.summarysize)(https://docs.julialang.org/en/v1/base/base/#Base.summarysize)

Finch.dropdefaultsFunction
dropdefaults(src)

Drop the default values from src and return a new tensor with the same shape and format.

Finch.dropdefaults!Function
dropdefaults!(dst, src)

Copy only the non- default values from src into dst. The shape and format of dst must match src