Skip to content

Commit 3c2e531

Browse files
Set up Documenter.jl documentation (#102)
Co-authored-by: Jeff Fessler <[email protected]>
1 parent b7c24b1 commit 3c2e531

20 files changed

+658
-402
lines changed

.github/workflows/TagBot.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ jobs:
99
- uses: JuliaRegistries/TagBot@v1
1010
with:
1111
token: ${{ secrets.GITHUB_TOKEN }}
12+
ssh: ${{ secrets.DOCUMENTER_KEY }}

.github/workflows/documentation.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: Documentation
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
tags: '*'
8+
pull_request:
9+
10+
jobs:
11+
build:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v2
15+
- uses: julia-actions/setup-julia@latest
16+
with:
17+
version: '1.5'
18+
- name: Install dependencies
19+
run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
20+
- name: Build and deploy
21+
env:
22+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # For authentication with GitHub Actions token
23+
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} # For authentication with SSH deploy key
24+
run: julia --project=docs/ docs/make.jl

README.md

Lines changed: 24 additions & 340 deletions
Large diffs are not rendered by default.

docs/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
build/
2+
site/

docs/Project.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[deps]
2+
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
3+
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
4+
LinearMaps = "7a12625a-238d-50fd-b39a-03d52299707e"
5+
6+
[compat]
7+
Documenter = "0.25"

docs/make.jl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using Documenter
2+
using LinearMaps
3+
using LinearAlgebra
4+
using SparseArrays
5+
6+
makedocs(
7+
sitename = "LinearMaps",
8+
format = Documenter.HTML(),
9+
modules = [LinearMaps],
10+
pages = Any[
11+
"Home" => "index.md",
12+
"Version history" => "history.md",
13+
"Types and methods" => "types.md",
14+
"Custom maps" => "custom.md",
15+
"Related packages" => "related.md"
16+
]
17+
)
18+
19+
# Documenter can also automatically deploy documentation to gh-pages.
20+
# See "Hosting Documentation" and deploydocs() in the Documenter manual
21+
# for more information.
22+
deploydocs(
23+
repo = "github.com/Jutho/LinearMaps.jl.git",
24+
push_preview=true
25+
)

docs/src/custom.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Defining custom `LinearMap` types
2+
3+
TBD

docs/src/history.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# What's new?
2+
3+
### What's new in v2.7
4+
* Potential reduction of memory allocations in multiplication of
5+
`LinearCombination`s, `BlockMap`s, and real- or complex-scaled `LinearMap`s.
6+
For the latter, a new internal type `ScaledMap` has been introduced.
7+
* Multiplication code for `CompositeMap`s has been refactored to facilitate to
8+
provide memory for storage of intermediate results by directly calling helper
9+
functions.
10+
11+
### What's new in v2.6
12+
* New feature: "lazy" Kronecker product, Kronecker sums, and powers thereof
13+
for `LinearMap`s. `AbstractMatrix` objects are promoted to `LinearMap`s if
14+
one of the first 8 Kronecker factors is a `LinearMap` object.
15+
* Compatibility with the generic multiply-and-add interface (a.k.a. 5-arg
16+
`mul!`) introduced in julia v1.3
17+
18+
### What's new in v2.5
19+
* New feature: concatenation of `LinearMap`s objects with `UniformScaling`s,
20+
consistent with (h-, v-, and hc-)concatenation of matrices. Note, matrices
21+
`A` must be wrapped as `LinearMap(A)`, `UniformScaling`s are promoted to
22+
`LinearMap`s automatically.
23+
24+
### What's new in v2.4
25+
* Support restricted to Julia v1.0+.
26+
27+
### What's new in v2.3
28+
* Fully Julia v0.7/v1.0/v1.1 compatible.
29+
* Full support of noncommutative number types such as quaternions.
30+
31+
### What's new in v2.2
32+
* Fully Julia v0.7/v1.0 compatible.
33+
* A `convert(SparseMatrixCSC, A::LinearMap)` function, that calls the `sparse`
34+
matrix generating function.
35+
36+
### What's new in v2.1
37+
* Fully Julia v0.7 compatible; dropped compatibility for previous versions of
38+
Julia from LinearMaps.jl v2.0.0 on.
39+
* A 5-argument version for `mul!(y, A::LinearMap, x, α=1, β=0)`, which
40+
computes `y := α * A * x + β * y` and implements the usual 3-argument
41+
`mul!(y, A, x)` for the default `α` and `β`.
42+
* Synonymous `convert(Matrix, A::LinearMap)` and `convert(Array, A::LinearMap)`
43+
functions, that call the `Matrix` constructor and return the matrix
44+
representation of `A`.
45+
* Multiplication with matrices, interpreted as a block row vector of vectors:
46+
* `mul!(Y::AbstractArray, A::LinearMap, X::AbstractArray, α=1, β=0)`:
47+
applies `A` to each column of `X` and stores the result in-place in the
48+
corresponding column of `Y`;
49+
* for the out-of-place multiplication, the approach is to compute
50+
`convert(Matrix, A * X)`; this is equivalent to applying `A` to each
51+
column of `X`. In generic code which handles both `A::AbstractMatrix` and
52+
`A::LinearMap`, the additional call to `convert` is a noop when `A` is a
53+
matrix.
54+
* Full compatibility with [Arpack.jl](https://github.com/JuliaLinearAlgebra/Arpack.jl)'s
55+
`eigs` and `svds`; previously only `eigs` was working. For more, nicely
56+
collaborating packages see the [Example](#example) section.

docs/src/index.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# LinearMaps.jl
2+
3+
*A Julia package for defining and working with linear maps, also known as linear transformations or linear operators acting on vectors. The only requirement for a LinearMap is that it can act on a vector (by multiplication) efficiently.*
4+
5+
## Installation
6+
7+
`LinearMaps.jl` is a registered package and can be installed via
8+
9+
pkg> add LinearMaps
10+
11+
in package mode, to be entered by typing `]` in the Julia REPL.
12+
13+
## Examples
14+
15+
Let
16+
17+
A = LinearMap(rand(10, 10))
18+
B = LinearMap(cumsum, reverse∘cumsum∘reverse, 10)
19+
20+
be a matrix- and function-based linear map, respectively. Then the following code just works,
21+
indistinguishably from the case when `A` and `B` are both `AbstractMatrix`-typed objects.
22+
23+
```
24+
3.0A + 2B
25+
A*B'
26+
[A B; B A]
27+
kron(A, B)
28+
```
29+
30+
The `LinearMap` type and corresponding methods combine well with the following packages:
31+
* [Arpack.jl](https://github.com/JuliaLinearAlgebra/Arpack.jl): iterative eigensolver
32+
`eigs` and SVD `svds`;
33+
* [IterativeSolvers.jl](https://github.com/JuliaMath/IterativeSolvers.jl): iterative
34+
solvers, eigensolvers, and SVD;
35+
* [KrylovKit.jl](https://github.com/Jutho/KrylovKit.jl): Krylov-based algorithms for linear problems, singular value and eigenvalue problems
36+
* [TSVD.jl](https://github.com/andreasnoack/TSVD.jl): truncated SVD `tsvd`.
37+
38+
```julia
39+
using LinearMaps
40+
import Arpack, IterativeSolvers, KrylovKit, TSVD
41+
42+
# Example 1, 1-dimensional Laplacian with periodic boundary conditions
43+
function leftdiff!(y::AbstractVector, x::AbstractVector) # left difference assuming periodic boundary conditions
44+
N = length(x)
45+
length(y) == N || throw(DimensionMismatch())
46+
@inbounds for i=1:N
47+
y[i] = x[i] - x[mod1(i-1, N)]
48+
end
49+
return y
50+
end
51+
52+
function mrightdiff!(y::AbstractVector, x::AbstractVector) # minus right difference
53+
N = length(x)
54+
length(y) == N || throw(DimensionMismatch())
55+
@inbounds for i=1:N
56+
y[i] = x[i] - x[mod1(i+1, N)]
57+
end
58+
return y
59+
end
60+
61+
D = LinearMap(leftdiff!, mrightdiff!, 100; ismutating=true) # by default has eltype(D) = Float64
62+
63+
Arpack.eigs(D'D; nev=3, which=:SR) # note that D'D is recognized as symmetric => real eigenfact
64+
Arpack.svds(D; nsv=3)
65+
66+
Σ, L = IterativeSolvers.svdl(D; nsv=3)
67+
68+
TSVD.tsvd(D, 3)
69+
70+
# Example 2, 1-dimensional Laplacian
71+
A = LinearMap(100; issymmetric=true, ismutating=true) do C, B
72+
C[1] = -2B[1] + B[2]
73+
for i in 2:length(B)-1
74+
C[i] = B[i-1] - 2B[i] + B[i+1]
75+
end
76+
C[end] = B[end-1] - 2B[end]
77+
return C
78+
end
79+
80+
Arpack.eigs(-A; nev=3, which=:SR)
81+
82+
# Example 3, 2-dimensional Laplacian
83+
Δ = kronsum(A, A)
84+
85+
Arpack.eigs(Δ; nev=3, which=:LR)
86+
KrylovKit.eigsolve(x -> Δ*x, size(Δ, 1), 3, :LR)
87+
```
88+
89+
## Philosophy
90+
91+
Several iterative linear algebra methods such as linear solvers or eigensolvers
92+
only require an efficient evaluation of the matrix-vector product, where the
93+
concept of a matrix can be formalized / generalized to a linear map (or linear
94+
operator in the special case of a square matrix).
95+
96+
The LinearMaps package provides the following functionality:
97+
98+
1. A `LinearMap` type that shares with the `AbstractMatrix` type that it
99+
responds to the functions `size`, `eltype`, `isreal`, `issymmetric`,
100+
`ishermitian` and `isposdef`, `transpose` and `adjoint` and multiplication
101+
with a vector using both `*` or the in-place version `mul!`. Linear algebra
102+
functions that use duck-typing for their arguments can handle `LinearMap`
103+
objects similar to `AbstractMatrix` objects, provided that they can be
104+
written using the above methods. Unlike `AbstractMatrix` types, `LinearMap`
105+
objects cannot be indexed, neither using `getindex` or `setindex!`.
106+
107+
2. A single function `LinearMap` that acts as a general purpose
108+
constructor (though it is only an abstract type) and allows to construct
109+
linear map objects from functions, or to wrap objects of type
110+
`AbstractMatrix` or `LinearMap`. The latter functionality is useful to
111+
(re)define the properties (`isreal`, `issymmetric`, `ishermitian`,
112+
`isposdef`) of the existing matrix or linear map.
113+
114+
3. A framework for combining objects of type `LinearMap` and of type
115+
`AbstractMatrix` using linear combinations, transposition, composition,
116+
concatenation and Kronecker product/sums,
117+
where the linear map resulting from these operations is never explicitly
118+
evaluated but only its matrix-vector product is defined (i.e. lazy
119+
evaluation). The matrix-vector product is written to minimize memory
120+
allocation by using a minimal number of temporary vectors. There is full
121+
support for the in-place version `mul!`, which should be preferred for
122+
higher efficiency in critical algorithms. In addition, it tries to recognize
123+
the properties of combinations of linear maps. In particular, compositions
124+
such as `A'*A` for arbitrary `A` or even `A'*B*C*B'*A` with arbitrary `A`
125+
and `B` and positive definite `C` are recognized as being positive definite
126+
and hermitian. In case a certain property of the resulting `LinearMap`
127+
object is not correctly inferred, the `LinearMap` method can be called to
128+
redefine the properties.

docs/src/related.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Related open-source packages
2+
3+
The following open-source packages provide similar or even extended functionality as
4+
`LinearMaps.jl`.
5+
6+
* [`Spot`: A linear-operator toolbox for Matlab](https://github.com/mpf/spot),
7+
which seems to have heavily inspired the Julia package
8+
[`LinearOperators.jl`](https://github.com/JuliaSmoothOptimizers/LinearOperators.jl)
9+
and the Python package [`PyLops`](https://github.com/equinor/pylops)
10+
11+
* [`fastmat`: fast linear transforms in Python](https://pypi.org/project/fastmat/)
12+
13+
* [`FunctionOperators.jl`](https://github.com/hakkelt/FunctionOperators.jl)
14+
and [`LinearMapsAA.jl`](https://github.com/JeffFessler/LinearMapsAA.jl)
15+
also support mappings between `Array`s, inspired by the `fatrix` object type in the
16+
[Matlab version of the Michigan Image Reconstruction Toolbox (MIRT)](https://github.com/JeffFessler/mirt).
17+
18+
As for lazy array manipulation (like addition, composition, Kronecker products and concatenation),
19+
there exist further related packages in the Julia ecosystem:
20+
21+
* [`LazyArrays.jl`](https://github.com/JuliaArrays/LazyArrays.jl)
22+
23+
* [`BlockArrays.jl`](https://github.com/JuliaArrays/BlockArrays.jl)
24+
25+
* [`BlockDiagonals.jl`](https://github.com/invenia/BlockDiagonals.jl)
26+
27+
* [`Kronecker.jl`](https://github.com/MichielStock/Kronecker.jl)
28+
29+
* [`FillArrays.jl`](https://github.com/JuliaArrays/FillArrays.jl)
30+
Since these packages provide types that are subtypes of Julia `Base`'s `AbstractMatrix` type,
31+
objects of those types can be wrapped by a `LinearMap` and freely mixed with, for instance,
32+
function-based linear maps. The same applies to custom matrix types as provided, for instance,
33+
by packages maintained by the [`JuliaArrays`](https://github.com/JuliaArrays) github organization.
34+
For any `CustomMatrix{T} <: AbstractMatrix{T}` type, you only need to provide a
35+
`mul!(::AbstractVecOrMat, ::CustomMatrix, ::AbstractVector[, ::Number, ::Number])` method for
36+
seamless integration with `LinearMaps.jl`.

0 commit comments

Comments
 (0)