-
Notifications
You must be signed in to change notification settings - Fork 4
Add support for sum and kronecker product of COO sparse matrices #45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,3 +3,5 @@ | |
| *.jl.mem | ||
| /Manifest.toml | ||
| /docs/build/ | ||
|
|
||
| .vscode | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -320,6 +320,64 @@ end | |
|
|
||
| +(D::Diagonal, A::SparseMatrixCOO) = A + D | ||
|
|
||
| function Base.:+(A::SparseMatrixCOO{T1}, B::SparseMatrixCOO{T2}) where {T1<:Number, T2<:Number} | ||
| A.n == B.n || throw(DimensionMismatch()) | ||
| A.m == B.m || throw(DimensionMismatch()) | ||
|
|
||
| T = promote_type(T1, T2) | ||
|
|
||
| rowval_colvalA = collect(zip(A.rows, A.cols)) | ||
| rowval_colvalB = collect(zip(B.rows, B.cols)) | ||
|
|
||
| rowval_colval = union(rowval_colvalA, rowval_colvalB) | ||
| rowval = first.(rowval_colval) | ||
| colval = last.(rowval_colval) | ||
|
|
||
| nzval = similar(rowval, T) | ||
| @inbounds for i in eachindex(rowval) | ||
| nzval[i] = zero(T) | ||
| for j in eachindex(rowval_colvalA) | ||
| if rowval_colvalA[j] == rowval_colval[i] | ||
| nzval[i] += A.vals[j] | ||
| break | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I am not wrong you assume here that each matrix has unique pair of (row, col) while I don't think it is necessary true.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But they should be unique, right? I mean, we should merge them in the moment of creating the sparse matrix, no?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Really sorry @albertomercurio , I completely lost track of this PR. There is a discussion on this https://github.com/orgs/JuliaSmoothOptimizers/discussions/51 , and the status is that QuadraticModels is not merging them by default. |
||
| end | ||
| end | ||
| for j in eachindex(rowval_colvalB) | ||
| if rowval_colvalB[j] == rowval_colval[i] | ||
| nzval[i] += B.vals[j] | ||
| break | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see comment above |
||
| end | ||
| end | ||
| end | ||
|
|
||
| return SparseMatrixCOO(A.m, A.n, rowval, colval, nzval) | ||
| end | ||
|
|
||
| function LinearAlgebra.kron(A::SparseMatrixCOO, B::SparseMatrixCOO) | ||
| mA, nA = size(A) | ||
| mB, nB = size(B) | ||
| out_shape = (mA * mB, nA * nB) | ||
| Annz = nnz(A) | ||
| Bnnz = nnz(B) | ||
|
|
||
| if Annz == 0 || Bnnz == 0 | ||
| return SparseMatrixCOO(Int[], Int[], T[], out_shape...) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be tested in the unit tests too |
||
| end | ||
|
|
||
| row = (A.rows .- 1) .* mB | ||
| row = repeat(row, inner = Bnnz) | ||
| col = (A.cols .- 1) .* nB | ||
| col = repeat(col, inner = Bnnz) | ||
| data = repeat(A.vals, inner = Bnnz) | ||
|
|
||
| row .+= repeat(B.rows, outer = Annz) | ||
| col .+= repeat(B.cols, outer = Annz) | ||
|
|
||
| data .*= repeat(B.vals, outer = Annz) | ||
|
|
||
| return SparseMatrixCOO(out_shape[1], out_shape[2], row, col, data) | ||
| end | ||
|
|
||
| # maximum! functions | ||
| replace_if_minusinf(val::T, replacement::T) where {T} = (val == -T(Inf)) ? replacement : val | ||
| function LinearAlgebra.maximum!(f::Function, v::AbstractVector{T}, A::SparseMatrixCOO{T}) where {T} | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there should be a more efficient to do this. The
unionwill iterate over both vectors, and to compute the sum you do it again. Would it be more efficient to do both at the same time?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the moment I don’t have anything in mind. Do you have an idea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, let's create an issue on the package after this PR is merge to point out to this as a possible improvement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does SparseMatrixCSC do it?