Skip to content

Commit aadcc06

Browse files
author
Wimmerer
committed
Mostly docs
1 parent 3eb4266 commit aadcc06

19 files changed

+347
-101
lines changed

Project.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ ContextVariablesX = "6add18c4-b38d-439d-96f6-d6bc489c04c5"
1212
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
1313
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1414
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
15-
MatrixDepot = "b51810bb-c9f3-55da-ae3c-350fc1fbce05"
1615
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
1716
SSGraphBLAS_jll = "7ed9a814-9cab-54e9-8e9e-d9e95b4d61b1"
1817
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

docs/make.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,17 @@ using SuiteSparseGraphBLAS
33

44
makedocs(
55
modules = [SuiteSparseGraphBLAS],
6-
sitename="SuiteSparse:GraphBLAS",
6+
sitename="SuiteSparseGraphBLAS.jl",
77
pages = [
88
"Introduction" => "index.md",
99
"Arrays" => "arrays.md",
10-
"Operations" => "operations.md"
10+
"Operations" => "operations.md",
11+
"Operators" => [
12+
"unaryops.md",
13+
"binaryops.md",
14+
"monoids.md",
15+
"semirings.md"
16+
]
1117
]
1218
)
1319

docs/src/index.md

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@ While the core library is mostly complete, and all GraphBLAS functionality is pr
99

1010
1. ChainRules.jl integration for AD.
1111
2. Complete SparseArrays and ArrayInterface interfaces.
12-
3. Import and Export in all formats including bitmap and csr. Currently only dense and csc are supported.
13-
4. Printing v2.
14-
5. User-defined types and functions.
15-
6. Alternative syntax for GraphBLAS ops (currently must use `BinaryOps.PLUS` instead of `+`).
16-
7. Complex builtins.
12+
3. Printing v2.
13+
4. User-defined types and functions.
14+
5. Alternative syntax for GraphBLAS ops (currently must use `BinaryOps.PLUS` instead of `+`).
15+
6. Complex builtins.
1716

1817
Once these are completed there will be a v1.0 release, with the goal being JuliaCon 2021.
1918

@@ -47,7 +46,7 @@ The SuiteSparse:GraphBLAS binary is installed automatically as `SSGraphBLAS_jll`
4746

4847
# Introduction
4948

50-
GraphBLAS harnesses the well-understood duality between graphs and matrices.
49+
GraphBLAS harnesses the well-understood duality between graphs and matrices.
5150
Specifically a graph can be represented by its [adjacency matrix](https://en.wikipedia.org/wiki/Adjacency_matrix), [incidence matrix](https://en.wikipedia.org/wiki/Incidence_matrix), or the many variations on those formats.
5251
With this matrix representation in hand we have a method to operate on the graph using linear algebra operations on the matrix.
5352

@@ -104,8 +103,8 @@ v = GBVector([4], [10])
104103
```
105104
## GraphBLAS Operations
106105

107-
A complete list of supported operations can be found in [Operations](@ref).
108-
GraphBLAS operations are, where possible, wrapped in existing Julia functions. The equivalent Julia functions are:
106+
The complete documentation of supported operations can be found in [Operations](@ref).
107+
GraphBLAS operations are, where possible, methods of existing Julia functions listed in the third column.
109108

110109
| GraphBLAS | Operation | Julia |
111110
|:--------------------|:----------------------------------------: |----------: |
@@ -126,25 +125,15 @@ GraphBLAS operations are, where possible, wrapped in existing Julia functions. T
126125

127126
where ``\bf M`` is a `GBArray` mask, ``\odot`` is a binary operator for accumulating into ``\bf C``, and ``\otimes`` and ``\oplus`` are a binary operation and commutative monoid respectively.
128127

129-
!!! note "assign vs subassign"
130-
131-
`subassign` is equivalent to `assign` except that the mask in `subassign` has the dimensions of ``\bf C(I,J)`` vs the dimensions of ``C`` for `assign`, and elements outside of the mask will never be modified by `subassign`.
132-
133128
### Common arguments
134129

135-
The operations above have a typical set of common arguments. These are:
130+
The operations above have often accept most or all of the following arguments.
136131

137-
#### `op` - `UnaryOp`, `BinaryOp`, `Monoid`, or `Semiring`:
132+
#### `op` - `UnaryOp`, `BinaryOp`, `Monoid`, `Semiring`, or `SelectOp`:
138133

139-
This is the key argument to most of these operations, which determines ``\oplus``, ``\otimes``, or ``f`` in the table above as well as the semiring used in `mul`.
134+
This is the most important argument for most of these operations. It determines ``\oplus``, ``\otimes``, or ``f`` in the table above as well as the semiring used in `mul`.
140135
Most operations are restricted to one type of operator.
141136

142-
!!! warning "Keyword vs Positional"
143-
For some operations like `mul` and `emul` this is a keyword argument which defaults to the typical arithmetic operators.
144-
For others like `map` this is the first argument, since there is no sensible default choice.
145-
146-
147-
148137
!!! tip "Built-Ins"
149138
The built-in operators can be found in the submodules: `UnaryOps`, `BinaryOps`, `Monoids`, and `Semirings`.
150139

@@ -157,12 +146,12 @@ The descriptor argument allows the user to modify the operation in some fashion.
157146
Transposes the inputs and can be found in `Descriptors.[T0 | T1 | T0T1]`.
158147
Typically you should use Julia's built-in transpose functionality.
159148

160-
- `desc.mask == [DEFAULT | STRUCTURE | COMPLEMENT | STRUCTURE + COMPLEMENT]`
149+
- `desc.mask == [DEFAULT | STRUCTURE | COMPLEMENT | STRUCT_COMP]`
161150

162151
If `STRUCTURE` is set the operation will use the presence of a value rather than the value itself to determine whether the index is masked.
163152
If `COMPLEMENT` is set the presence/truth value is complemented (ie. if **no** value is present or the value is **false** that index is masked).
164153

165-
- `desc.output` == [DEFAULT | REPLACE]
154+
- `desc.output == [DEFAULT | REPLACE]`
166155

167156
If `REPLACE` is set the operation will replace all values in the output matrix **after** the accumulation step.
168157
If an index is found in the output matrix, but not in the results of the operation it will be set to `nothing`.
@@ -177,18 +166,7 @@ The accumulation step is performed **before** masking.
177166

178167
The `mask` keyword argument determines whether each index from the result of an operation appears in the output.
179168
The mask may be structural, where the presence of a value indicates the mask is `true`, or valued where the value of the mask indicates its truth value.
180-
The mask may also be complemented.
181-
182-
183-
### Order of Operations
184-
185-
A GraphBLAS operation occurs in the following order (steps are skipped when possible):
186-
187-
1. Calculate `T = <operation>(args...)`
188-
2. Elementwise accumulate `Z[i,j] = accum(C[i,j], T[i,j])`
189-
3. Optionally masked assignment `C[i,j] = mask[i,j] ? Z[i,j] : [nothing | C[i,j]]`
190-
191-
If `REPLACE` is set the option in step 3. is `nothing`, otherwise it is `C[i,j]`.
169+
The mask may also be complemented. These options are controlled by the `desc` argument.
192170

193171
## GraphBLAS Operators
194172

@@ -214,7 +192,25 @@ BOR COPYSIGN FIRSTJ ISEQ LAND MAX POW SECO
214192

215193
## Example
216194

195+
Here is an example of several different methods of triangle counting with GraphBLAS.
196+
The methods are drawn from the LAGraph [repo](https://github.com/GraphBLAS/LAGraph).
217197

198+
Input `A` must be a square, symmetric matrix with any element type.
199+
We'll test it using the matrix from the GBArray section above, which has two triangles in its undirected form.
218200

219201
```julia
202+
function cohen(A)
203+
U = select(SelectOps.TRIU, A)
204+
L = select(SelectOps.TRIL, A)
205+
return reduce(Monoids.PLUS_MONOID[Int64], mul(L, U, Semirings.PLUS_PAIR; mask=A)) ÷ 2
206+
end
207+
208+
function sandia(A)
209+
L = select(SelectOps.TRIL, A)
210+
return reduce(Monoids.PLUS_MONOID[Int64], mul(L, L, Semirings.PLUS_PAIR; mask=L))
211+
end
212+
213+
M = eadd(A, A', BinaryOps.PLUS) #Make undirected/symmetric
214+
cohen(A) # 2
215+
sandia(A) # 2
220216
```

docs/src/operations.md

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,54 @@
1-
# Operations
1+
# Operations
2+
3+
GraphBLAS operations cover most of the typical linear algebra operations on arrays in Julia.
4+
5+
## Correspondence of GraphBLAS C functions and Julia functions
6+
7+
| GraphBLAS | Operation | Julia |
8+
|:--------------------|:----------------------------------------: |----------: |
9+
|`mxm`, `mxv`, `vxm` |``\bf C \langle M \rangle = C \odot AB`` |`mul[!]` |
10+
|`eWiseMult` |``\bf C \langle M \rangle = C \odot (A \otimes B)`` |`emul[!]` |
11+
|`eWiseAdd` |``\bf C \langle M \rangle = C \odot (A \oplus B)`` |`eadd[!]` |
12+
|`extract` |``\bf C \langle M \rangle = C \odot A(I,J)`` |`extract[!]`, `getindex` |
13+
|`subassign` |``\bf C (I,J) \langle M \rangle = C(I,J) \odot A`` |`subassign[!]`, `setindex!` |
14+
|`assign` |``\bf C \langle M \rangle (I,J) = C(I,J) \odot A`` |`assign[!]` |
15+
|`apply` |``{\bf C \langle M \rangle = C \odot} f{\bf (A)}`` |`map[!]` |
16+
| |``{\bf C \langle M \rangle = C \odot} f({\bf A},y)`` | |
17+
| |``{\bf C \langle M \rangle = C \odot} f(x,{\bf A})`` | |
18+
|`select` |``{\bf C \langle M \rangle = C \odot} f({\bf A},k)`` |`select[!]` |
19+
|`reduce` |``{\bf w \langle m \rangle = w \odot} [{\oplus}_j {\bf A}(:,j)]`` |`reduce[!]` |
20+
| |``s = s \odot [{\oplus}_{ij} {\bf A}(i,j)]`` | |
21+
|`transpose` |``\bf C \langle M \rangle = C \odot A^{\sf T}`` |`gbtranspose[!]`, lazy: `transpose`, `'` |
22+
|`kronecker` |``\bf C \langle M \rangle = C \odot \text{kron}(A, B)`` |`kron[!]` |
23+
24+
where ``\bf M`` is a `GBArray` mask, ``\odot`` is a binary operator for accumulating into ``\bf C``, and ``\otimes`` and ``\oplus`` are a binary operation and commutative monoid respectively.
25+
26+
!!! note "assign vs subassign"
27+
`subassign` is equivalent to `assign` except that the mask in `subassign` has the dimensions of ``\bf C(I,J)`` vs the dimensions of ``C`` for `assign`, and elements outside of the mask will never be modified by `subassign`. See the [GraphBLAS User Guide](https://github.com/DrTimothyAldenDavis/GraphBLAS/blob/stable/Doc/GraphBLAS_UserGuide.pdf) for more details.
28+
29+
## Order of Operations
30+
31+
A GraphBLAS operation occurs in the following order (steps are skipped when possible):
32+
33+
1. Calculate `T = <operation>(args...)`
34+
2. Elementwise accumulate `Z[i,j] = accum(C[i,j], T[i,j])`
35+
3. Optionally masked assignment `C[i,j] = mask[i,j] ? Z[i,j] : [nothing | C[i,j]]`
36+
37+
If `REPLACE` is set the option in step 3. is `nothing`, otherwise it is `C[i,j]`.
38+
39+
## Operation Documentation
40+
41+
```@docs
42+
mul
43+
emul
44+
eadd
45+
extract
46+
extract!
47+
subassign!
48+
assign!
49+
map
50+
select
51+
reduce
52+
gbtranspose
53+
kron
54+
```

docs/src/operators.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Operators

docs/src/unaryops.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Unary Operators
2+
3+
```@autodocs
4+
Modules = [SuiteSparseGraphBLAS]
5+
Pages = ["unaryops.jl"]
6+
```

src/SuiteSparseGraphBLAS.jl

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ const OperatorUnion = Union{
6363
GrBOp
6464
}
6565

66+
#Context variables for the `with` function
6667
@contextvar ctxop::OperatorUnion
6768
@contextvar ctxmask::Union{GBArray, Ptr} = C_NULL
6869
@contextvar ctxaccum::Union{BinaryUnion, Ptr} = C_NULL
@@ -93,17 +94,18 @@ include("options.jl")
9394
include("misc.jl")
9495
export libgb
9596
export UnaryOps, BinaryOps, Monoids, Semirings, SelectOps, Descriptors #Submodules
97+
export Descriptor #Types
9698
export xtype, ytype, ztype
9799
export GBScalar, GBVector, GBMatrix #arrays
98100
export clear!, extract, extract!, subassign!, assign! #array functions
99101

100102
#operations
101103
export mul, select, select!, eadd, eadd!, emul, emul!, map, map!, gbtranspose, gbtranspose!
102104
# Reexports.
103-
export diag, Diagonal, mul!, kron, kron!, transpose
105+
export diag, Diagonal, mul!, kron, kron!, transpose, reduce
104106
export nnz, sprand, findnz
105107

106-
#with function
108+
#context/with
107109
export with
108110

109111
function __init__()
@@ -121,7 +123,4 @@ function __init__()
121123
end
122124
end
123125

124-
#We need to do this after __init__
125-
126-
127126
end #end of module

src/descriptors.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ end
9595
#This is probably not ideal. Perhaps kwargs = nothing by default is better
9696
Base.:+(d1::Descriptor, ::Nothing) = d1
9797
Base.:+(::Nothing, d2::Descriptor) = d2
98-
98+
Base.:+(f1::libgb.GrB_Desc_Value, f2::libgb.GrB_Desc_Value) = libgb.GrB_Desc_Value(UInt32(f1) + UInt32(f2))
9999
function Base.propertynames(d::Descriptor)
100100
return (
101101
:output,
@@ -117,6 +117,7 @@ GxB_DEFAULT,
117117
GrB_REPLACE,
118118
GrB_COMP,
119119
GrB_STRUCTURE,
120+
GrB_STRUCT_COMP,
120121
GrB_TRAN,
121122
GxB_GPU_ALWAYS,
122123
GxB_GPU_NEVER,
@@ -131,6 +132,7 @@ const DEFAULT = GxB_DEFAULT
131132
const REPLACE = GrB_REPLACE
132133
const COMPLEMENT = GrB_COMP
133134
const STRUCTURE = GrB_STRUCTURE
135+
const STRUCT_COMP = GrB_STRUCT_COMP
134136
const TRANSPOSE = GrB_TRAN
135137
const GUSTAVSON = GxB_AxB_GUSTAVSON
136138
const DOT = GxB_AxB_DOT

src/lib/LibGraphBLAS.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ end
9797
GrB_COMP = 2
9898
# GrB_SCMP = 2
9999
GrB_STRUCTURE = 4
100+
GrB_STRUCT_COMP = 6
100101
GrB_TRAN = 3
101102
GxB_GPU_ALWAYS = 2001
102103
GxB_GPU_NEVER = 2002

src/matrix.jl

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ end
305305
"""
306306
assign!(C::GBMatrix, A::GBMatrix, I, J; kwargs...)::GBMatrix
307307
308-
Assign a submatrix of `C` to `A`. Equivalent to [`subassign`](@ref) except that
308+
Assign a submatrix of `C` to `A`. Equivalent to [`subassign!`](@ref) except that
309309
`size(mask) == size(C)`, whereas `size(mask) == size(A) in `subassign!`.
310310
311311
# Arguments
@@ -392,3 +392,18 @@ function Base.setindex(
392392
)
393393
throw("Not implemented")
394394
end
395+
396+
#Printing fixes:
397+
function Base.isstored(A::GBArray, i::Integer, j::Integer)
398+
@boundscheck checkbounds(A, i, j)
399+
if A[i, j] === nothing
400+
return false
401+
else
402+
return true
403+
end
404+
end
405+
406+
#Help wanted: This isn't really centered for a lot of eltypes.
407+
function Base.replace_in_print_matrix(A::GBArray, i::Integer, j::Integer, s::AbstractString)
408+
Base.isstored(A, i, j) ? s : Base.replace_with_centered_mark(s)
409+
end

0 commit comments

Comments
 (0)