Skip to content

Commit 6e4c9f1

Browse files
committed
Merge pull request #13440 from JuliaLang/mb/sparsevec
RFC: SparseVectors, Take 2
2 parents 8adbf7a + eb90416 commit 6e4c9f1

23 files changed

+2339
-298
lines changed

NEWS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ Library improvements
3737

3838
* New method for generic QR with column pivoting ([#13480]).
3939

40+
* A new `SparseVector` type allows for one-dimensional sparse arrays. Slicing
41+
and reshaping sparse matrices now return vectors when appropriate. The
42+
`sparsevec` function returns a one-dimensional sparse vector instead of a
43+
one-column sparse matrix.
44+
4045
Deprecated or removed
4146
---------------------
4247

base/deprecated.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,3 +852,5 @@ end
852852
@deprecate cor(X::AbstractMatrix; vardim=1, mean=Base.mean(X, vardim)) corm(X, mean, vardim)
853853
@deprecate cor(x::AbstractVector, y::AbstractVector; mean=(Base.mean(x), Base.mean(y))) corm(x, mean[1], y, mean[2])
854854
@deprecate cor(X::AbstractVecOrMat, Y::AbstractVecOrMat; vardim=1, mean=(Base.mean(X, vardim), Base.mean(Y, vardim))) corm(X, mean[1], Y, mean[2], vardim)
855+
856+
@deprecate_binding SparseMatrix SparseArrays

base/docs/helpdb.jl

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2387,17 +2387,6 @@ Right division operator: multiplication of `x` by the inverse of `y` on the righ
23872387
"""
23882388
Base.(:(/))
23892389

2390-
doc"""
2391-
ldltfact(::Union{SparseMatrixCSC,Symmetric{Float64,SparseMatrixCSC{Flaot64,SuiteSparse_long}},Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},SuiteSparse_long}}}; shift=0, perm=Int[]) -> CHOLMOD.Factor
2392-
2393-
Compute the `LDLt` factorization of a sparse symmetric or Hermitian matrix. A fill-reducing permutation is used. `F = ldltfact(A)` is most frequently used to solve systems of equations `A*x = b` with `F\b`, but also the methods `diag`, `det`, `logdet` are defined for `F`. You can also extract individual factors from `F`, using `F[:L]`. However, since pivoting is on by default, the factorization is internally represented as `A == P'*L*D*L'*P` with a permutation matrix `P`; using just `L` without accounting for `P` will give incorrect answers. To include the effects of permutation, it's typically preferable to extact "combined" factors like `PtL = F[:PtL]` (the equivalent of `P'*L`) and `LtP = F[:UP]` (the equivalent of `L'*P`). The complete list of supported factors is `:L, :PtL, :D, :UP, :U, :LD, :DU, :PtLD, :DUP`.
2394-
2395-
Setting optional `shift` keyword argument computes the factorization of `A+shift*I` instead of `A`. If the `perm` argument is nonempty, it should be a permutation of `1:size(A,1)` giving the ordering to use (instead of CHOLMOD's default AMD ordering).
2396-
2397-
The function calls the C library CHOLMOD and many other functions from the library are wrapped but not exported.
2398-
"""
2399-
ldltfact(A::SparseMatrixCSC; shift=0, perm=Int[])
2400-
24012390
doc"""
24022391
connect([host],port) -> TcpSocket
24032392
@@ -7256,13 +7245,6 @@ Tests whether `A` or its elements are of type `T`.
72567245
"""
72577246
iseltype
72587247

7259-
doc"""
7260-
symperm(A, p)
7261-
7262-
Return the symmetric permutation of `A`, which is `A[p,p]`. `A` should be symmetric and sparse, where only the upper triangular part of the matrix is stored. This algorithm ignores the lower triangular part of the matrix. Only the upper triangular part of the result is returned as well.
7263-
"""
7264-
symperm
7265-
72667248
doc"""
72677249
min(x, y, ...)
72687250
@@ -9993,15 +9975,6 @@ Like permute!, but the inverse of the given permutation is applied.
99939975
"""
99949976
ipermute!
99959977

9996-
doc"""
9997-
```rst
9998-
.. full(S)
9999-
10000-
Convert a sparse matrix ``S`` into a dense matrix.
10001-
```
10002-
"""
10003-
full(::AbstractSparseMatrix)
10004-
100059978
doc"""
100069979
```rst
100079980
.. full(F)
@@ -10487,13 +10460,6 @@ k]``.)
1048710460
"""
1048810461
eigfact(A,B)
1048910462

10490-
doc"""
10491-
rowvals(A)
10492-
10493-
Return a vector of the row indices of `A`, and any modifications to the returned vector will mutate `A` as well. Given the internal storage format of sparse matrices, providing access to how the row indices are stored internally can be useful in conjuction with iterating over structural nonzero values. See `nonzeros(A)` and `nzrange(A, col)`.
10494-
"""
10495-
rowvals
10496-
1049710463
doc"""
1049810464
mkdir(path, [mode])
1049910465

base/exports.jl

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,12 @@ export
2020
BLAS,
2121
LAPACK,
2222
Serializer,
23-
SparseMatrix,
2423
Docs,
2524
Markdown,
2625

2726
# Types
2827
AbstractChannel,
2928
AbstractMatrix,
30-
AbstractSparseArray,
31-
AbstractSparseMatrix,
32-
AbstractSparseVector,
3329
AbstractVector,
3430
AbstractVecOrMat,
3531
Array,
@@ -107,7 +103,6 @@ export
107103
SharedArray,
108104
SharedMatrix,
109105
SharedVector,
110-
SparseMatrixCSC,
111106
StatStruct,
112107
StepRange,
113108
StridedArray,
@@ -562,7 +557,6 @@ export
562557
minimum,
563558
minmax,
564559
ndims,
565-
nnz,
566560
nonzeros,
567561
nthperm!,
568562
nthperm,
@@ -715,21 +709,7 @@ export
715709
×,
716710

717711
# sparse
718-
etree,
719712
full,
720-
issparse,
721-
sparse,
722-
sparsevec,
723-
spdiagm,
724-
speye,
725-
spones,
726-
sprand,
727-
sprandbool,
728-
sprandn,
729-
spzeros,
730-
symperm,
731-
rowvals,
732-
nzrange,
733713

734714
# bitarrays
735715
bitpack,
@@ -1434,4 +1414,27 @@ export
14341414
@assert,
14351415
@enum,
14361416
@label,
1437-
@goto
1417+
@goto,
1418+
1419+
# SparseArrays module re-exports
1420+
SparseArrays,
1421+
AbstractSparseArray,
1422+
AbstractSparseMatrix,
1423+
AbstractSparseVector,
1424+
SparseMatrixCSC,
1425+
SparseVector,
1426+
etree,
1427+
issparse,
1428+
sparse,
1429+
sparsevec,
1430+
spdiagm,
1431+
speye,
1432+
spones,
1433+
sprand,
1434+
sprandbool,
1435+
sprandn,
1436+
spzeros,
1437+
symperm,
1438+
rowvals,
1439+
nzrange,
1440+
nnz

base/irrationals.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,9 @@ const golden = φ
122122
for T in (Irrational, Rational, Integer, Number)
123123
^(::Irrational{:e}, x::T) = exp(x)
124124
end
125-
for T in (Range, BitArray, SparseMatrixCSC, StridedArray, AbstractArray)
125+
for T in (Range, BitArray, StridedArray, AbstractArray)
126126
.^(::Irrational{:e}, x::T) = exp(x)
127127
end
128-
^(::Irrational{:e}, x::AbstractMatrix) = expm(x)
129128

130129
log(::Irrational{:e}) = 1 # use 1 to correctly promote expressions like log(x)/log(e)
131130
log(::Irrational{:e}, x) = log(x)

base/precompile.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,6 @@ precompile(Base.next, (Dict{Symbol,Any},Int))
294294
precompile(Base.next, (IntSet, Int))
295295
precompile(Base.next, (UnitRange{Int},Int))
296296
precompile(Base.nextind, (ASCIIString, Int))
297-
precompile(Base.nnz, (BitArray{1},))
298297
precompile(Base.normpath, (ASCIIString, ASCIIString))
299298
precompile(Base.normpath, (ASCIIString,))
300299
precompile(Base.normpath, (UTF8String, UTF8String))

base/sparse.jl

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,38 @@
11
# This file is a part of Julia. License is MIT: http://julialang.org/license
22

3-
module SparseMatrix
3+
module SparseArrays
44

55
using Base: Func, AddFun, OrFun, ConjFun, IdFun
66
using Base.Sort: Forward
77
using Base.LinAlg: AbstractTriangular, PosDefException
88

99
import Base: +, -, *, &, |, $, .+, .-, .*, ./, .\, .^, .<, .!=, ==
10-
import Base: A_mul_B!, Ac_mul_B, Ac_mul_B!, At_mul_B!, A_ldiv_B!
11-
import Base: @get!, abs, abs2, broadcast, ceil, complex, cond, conj, convert, copy,
12-
ctranspose, diagm, exp, expm1, factorize, find, findmax, findmin, findnz, float,
13-
full, getindex, hcat, hvcat, imag, indmax, ishermitian, kron, length, log, log1p,
14-
max, min, norm, one, promote_eltype, real, reinterpret, reshape, rot180, rotl90,
15-
rotr90, round, scale, scale!, setindex!, similar, size, transpose, tril, triu, vcat,
16-
vec
10+
import Base: A_mul_B!, Ac_mul_B, Ac_mul_B!, At_mul_B, At_mul_B!, A_ldiv_B!
11+
12+
import Base: @get!, acos, acosd, acot, acotd, acsch, asech, asin, asind, asinh,
13+
atan, atand, atanh, broadcast!, chol, conj!, cos, cosc, cosd, cosh, cospi, cot,
14+
cotd, coth, countnz, csc, cscd, csch, ctranspose!, diag, diff, done, dot, eig,
15+
exp10, exp2, eye, findn, floor, hash, indmin, inv, issym, istril, istriu, log10,
16+
log2, lu, maxabs, minabs, next, sec, secd, sech, show, showarray, sin, sinc,
17+
sind, sinh, sinpi, squeeze, start, sum, sumabs, sumabs2, summary, tan, tand,
18+
tanh, trace, transpose!, tril!, triu!, trunc, vecnorm, writemime, abs, abs2,
19+
broadcast, call, ceil, complex, cond, conj, convert, copy, ctranspose, diagm,
20+
exp, expm1, factorize, find, findmax, findmin, findnz, float, full, getindex,
21+
hcat, hvcat, imag, indmax, ishermitian, kron, length, log, log1p, max, min,
22+
maximum, minimum, norm, one, promote_eltype, real, reinterpret, reshape, rot180,
23+
rotl90, rotr90, round, scale, scale!, setindex!, similar, size, transpose, tril,
24+
triu, vcat, vec
25+
1726
import Base.Broadcast: eltype_plus, broadcast_shape
1827

19-
export AbstractSparseArray, AbstractSparseMatrix, AbstractSparseVector, SparseMatrixCSC,
20-
blkdiag, dense, droptol!, dropzeros!, etree, issparse, nnz, nonzeros, nzrange,
21-
rowvals, sparse, sparsevec, spdiagm, speye, spones, sprand, sprandbool, sprandn,
22-
spzeros, symperm
28+
export AbstractSparseArray, AbstractSparseMatrix, AbstractSparseVector,
29+
SparseMatrixCSC, SparseVector, blkdiag, dense, droptol!, dropzeros!, etree,
30+
issparse, nonzeros, nzrange, rowvals, sparse, sparsevec, spdiagm, speye, spones,
31+
sprand, sprandbool, sprandn, spzeros, symperm, nnz
2332

2433
include("sparse/abstractsparse.jl")
2534
include("sparse/sparsematrix.jl")
35+
include("sparse/sparsevector.jl")
2636
include("sparse/csparse.jl")
2737

2838
include("sparse/linalg.jl")
@@ -32,4 +42,4 @@ if Base.USE_GPL_LIBS
3242
include("sparse/spqr.jl")
3343
end
3444

35-
end # module SparseMatrix
45+
end

base/sparse/cholmod.jl

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ import Base.LinAlg: (\), A_mul_Bc, A_mul_Bt, Ac_ldiv_B, Ac_mul_B, At_ldiv_B, At_
99
cholfact, det, diag, ishermitian, isposdef,
1010
issym, ldltfact, logdet
1111

12-
import Base.SparseMatrix: sparse, nnz
12+
importall ..SparseArrays
1313

1414
export
1515
Dense,
1616
Factor,
1717
Sparse
1818

19-
using Base.SparseMatrix: AbstractSparseMatrix, SparseMatrixCSC, increment, indtype
19+
import ..SparseArrays: AbstractSparseMatrix, SparseMatrixCSC, increment, indtype
2020

2121
#########
2222
# Setup #
@@ -853,6 +853,9 @@ function convert{Tv<:VTypes}(::Type{Sparse}, A::SparseMatrixCSC{Tv,SuiteSparse_l
853853

854854
return o
855855
end
856+
857+
# convert SparseVectors into CHOLMOD Sparse types through a mx1 CSC matrix
858+
convert{Tv<:VTypes}(::Type{Sparse}, A::SparseVector{Tv,SuiteSparse_long}) = convert(Sparse, convert(SparseMatrixCSC, A))
856859
function convert{Tv<:VTypes}(::Type{Sparse}, A::SparseMatrixCSC{Tv,SuiteSparse_long})
857860
o = Sparse(A, 0)
858861
# check if array is symmetric and change stype if it is
@@ -994,7 +997,7 @@ function sparse(F::Factor)
994997
L, d = getLd!(LD)
995998
A = scale(L, d)*L'
996999
end
997-
SparseMatrix.sortSparseMatrixCSC!(A)
1000+
SparseArrays.sortSparseMatrixCSC!(A)
9981001
p = get_perm(F)
9991002
if p != [1:s.n;]
10001003
pinv = Array(Int, length(p))
@@ -1216,6 +1219,32 @@ function cholfact(A::Sparse; kws...)
12161219
return F
12171220
end
12181221

1222+
doc"""
1223+
ldltfact(::Union{SparseMatrixCSC,Symmetric{Float64,SparseMatrixCSC{Flaot64,SuiteSparse_long}},Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},SuiteSparse_long}}}; shift=0, perm=Int[]) -> CHOLMOD.Factor
1224+
1225+
Compute the `LDLt` factorization of a sparse symmetric or Hermitian matrix. A
1226+
fill-reducing permutation is used. `F = ldltfact(A)` is most frequently used to
1227+
solve systems of equations `A*x = b` with `F\b`. The returned factorization
1228+
object `F` also supports the methods `diag`, `det`, and `logdet`. You can
1229+
extract individual factors from `F` using `F[:L]`. However, since pivoting is
1230+
on by default, the factorization is internally represented as `A == P'*L*D*L'*P`
1231+
with a permutation matrix `P`; using just `L` without accounting for `P` will
1232+
give incorrect answers. To include the effects of permutation, it's typically
1233+
preferable to extact "combined" factors like `PtL = F[:PtL]` (the equivalent of
1234+
`P'*L`) and `LtP = F[:UP]` (the equivalent of `L'*P`). The complete list of
1235+
supported factors is `:L, :PtL, :D, :UP, :U, :LD, :DU, :PtLD, :DUP`.
1236+
1237+
Setting optional `shift` keyword argument computes the factorization of
1238+
`A+shift*I` instead of `A`. If the `perm` argument is nonempty, it should be a
1239+
permutation of `1:size(A,1)` giving the ordering to use (instead of CHOLMOD's
1240+
default AMD ordering).
1241+
1242+
The function calls the C library CHOLMOD and many other functions from the
1243+
library are wrapped but not exported.
1244+
1245+
"""
1246+
ldltfact(A::SparseMatrixCSC; shift=0, perm=Int[])
1247+
12191248
function ldltfact(A::Sparse; kws...)
12201249
cm = defaults(common()) # setting the common struct to default values. Should only be done when creating new factorization.
12211250
set_print_level(cm, 0) # no printing from CHOLMOD by default
@@ -1294,13 +1323,15 @@ for (T, f) in ((:Dense, :solve), (:Sparse, :spsolve))
12941323
end
12951324
end
12961325

1326+
typealias SparseVecOrMat{Tv,Ti} Union{SparseVector{Tv,Ti}, SparseMatrixCSC{Tv,Ti}}
1327+
12971328
function (\)(L::FactorComponent, b::Vector)
12981329
reshape(convert(Matrix, L\Dense(b)), length(b))
12991330
end
13001331
function (\)(L::FactorComponent, B::Matrix)
13011332
convert(Matrix, L\Dense(B))
13021333
end
1303-
function (\)(L::FactorComponent, B::SparseMatrixCSC)
1334+
function (\)(L::FactorComponent, B::SparseVecOrMat)
13041335
sparse(L\Sparse(B,0))
13051336
end
13061337

@@ -1311,12 +1342,12 @@ Ac_ldiv_B(L::FactorComponent, B) = ctranspose(L)\B
13111342
(\)(L::Factor, B::Matrix) = convert(Matrix, solve(CHOLMOD_A, L, Dense(B)))
13121343
(\)(L::Factor, B::Sparse) = spsolve(CHOLMOD_A, L, B)
13131344
# When right hand side is sparse, we have to ensure that the rhs is not marked as symmetric.
1314-
(\)(L::Factor, B::SparseMatrixCSC) = sparse(spsolve(CHOLMOD_A, L, Sparse(B, 0)))
1345+
(\)(L::Factor, B::SparseVecOrMat) = sparse(spsolve(CHOLMOD_A, L, Sparse(B, 0)))
13151346

13161347
Ac_ldiv_B(L::Factor, B::Dense) = solve(CHOLMOD_A, L, B)
13171348
Ac_ldiv_B(L::Factor, B::VecOrMat) = convert(Matrix, solve(CHOLMOD_A, L, Dense(B)))
13181349
Ac_ldiv_B(L::Factor, B::Sparse) = spsolve(CHOLMOD_A, L, B)
1319-
Ac_ldiv_B(L::Factor, B::SparseMatrixCSC) = Ac_ldiv_B(L, Sparse(B))
1350+
Ac_ldiv_B(L::Factor, B::SparseVecOrMat) = Ac_ldiv_B(L, Sparse(B))
13201351

13211352
## Other convenience methods
13221353
function diag{Tv}(F::Factor{Tv})
@@ -1398,7 +1429,7 @@ function ishermitian(A::Sparse{Complex{Float64}})
13981429
end
13991430
end
14001431

1401-
(*){Ti}(A::Symmetric{Float64,SparseMatrixCSC{Float64,Ti}}, B::SparseMatrixCSC{Float64,Ti}) = sparse(Sparse(A)*Sparse(B))
1402-
(*){Ti}(A::Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},Ti}}, B::SparseMatrixCSC{Complex{Float64},Ti}) = sparse(Sparse(A)*Sparse(B))
1432+
(*){Ti}(A::Symmetric{Float64,SparseMatrixCSC{Float64,Ti}}, B::SparseVecOrMat{Float64,Ti}) = sparse(Sparse(A)*Sparse(B))
1433+
(*){Ti}(A::Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},Ti}}, B::SparseVecOrMat{Complex{Float64},Ti}) = sparse(Sparse(A)*Sparse(B))
14031434

14041435
end #module

base/sparse/csparse.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,17 @@ function csc_permute{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, pinv::Vector{Ti}, q::Vect
313313
(C.').' # double transpose to order the columns
314314
end
315315

316+
316317
# based on cs_symperm p. 21, "Direct Methods for Sparse Linear Systems"
317318
# form A[p,p] for a symmetric A stored in the upper triangle
319+
doc"""
320+
symperm(A, p)
321+
322+
Return the symmetric permutation of `A`, which is `A[p,p]`. `A` should be
323+
symmetric, sparse, and only contain nonzeros in the upper triangular part of the
324+
matrix is stored. This algorithm ignores the lower triangular part of the
325+
matrix. Only the upper triangular part of the result is returned.
326+
"""
318327
function symperm{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, pinv::Vector{Ti})
319328
m, n = size(A)
320329
if m != n

base/sparse/linalg.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ function spmatmul{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti};
160160

161161
# The Gustavson algorithm does not guarantee the product to have sorted row indices.
162162
Cunsorted = SparseMatrixCSC(mA, nB, colptrC, rowvalC, nzvalC)
163-
C = Base.SparseMatrix.sortSparseMatrixCSC!(Cunsorted, sortindices=sortindices)
163+
C = SparseArrays.sortSparseMatrixCSC!(Cunsorted, sortindices=sortindices)
164164
return C
165165
end
166166

@@ -752,7 +752,7 @@ inv(A::SparseMatrixCSC) = error("The inverse of a sparse matrix can often be den
752752

753753
## scale methods
754754

755-
# Copy colptr and rowval from one SparseMatrix to another
755+
# Copy colptr and rowval from one sparse matrix to another
756756
function copyinds!(C::SparseMatrixCSC, A::SparseMatrixCSC)
757757
if C.colptr !== A.colptr
758758
resize!(C.colptr, length(A.colptr))

0 commit comments

Comments
 (0)