Hello,
I would like to populate a sparse matrix A
with a function f:\mathbb{N}\times \mathbb{N} \to \mathbb{R}, (i_1, i_2) \mapsto f(i_1, i_2) which is symmetric, i.e. f(i_1, i_2) = f(i_2, i_1). We want to fill A
such that A[i_1, i_2] = f(i_1, i_2)
. The sparsity pattern of A
is known and symmetric. I would like to reduce functions evaluations by using the symmetry of f when filling A
.
If A
is stored in the CSC format, how do you determine which indices correspond to a pair (i_1, i_2) and its symmetric (i_2, i_1) from A.colptr
and A.rowval
?
The sparsity pattern of A
is given by a function \operatorname{sparsity\_pattern}(i_1, i_2). I would like to compute the sparsity pattern store it in a matrix pattern
and transfer it when initializing A
. Is there a better way to proceed?
Some MWE:
using LinearAlgebra
using SparseArrays
f(i1, i2) = 2.0*(i1+i2)
# sparsity_pattern depends on a third entry i3 but is symmetric in i1 and i2
sparsity_pattern(i1, i2, i3) = (mod(i1 + i2 + i3, 2) == 0 && i1 + i2 >= i3 && i1 + i3 >= i2 && i2 + i3 >= i1)
order = 5
pattern = zeros(Int64, order, order)
for i1=1:order
# Use symmetry
for i2=i1:order
if sparsity_pattern(i1, i2, order) == true
pattern[i1, i2] = 1
pattern[i2, i1] = 1
end
end
end
pattern = sparse(pattern)
rows, cols, _ = findnz(pattern)
# Initialize A by transferring sparsity pattern of pattern
# Probably a better way using similar(pattern, Float64), not sure of the precise syntax
# A = SparseMatrixCSC(order, order, pattern.colptr, pattern.rowval,
# Array{Float64}(undef,length(pattern.rowval)))
# Cleaner way
A = sparse(rows, cols, Array{Float64}(undef,length(rows)))
# Populate A without using the symmetry of f(i1, i2)
for (i1, i2) in zip(rows, cols)
A[i1,i2] = f(i1, i2)
end
Thank you for your help,