Skip to content

Commit 148828d

Browse files
committed
Update docstring references
As a follow-up (patch?) to #47, we remove the Markdown-style [^ABC] references from the docstrings and keep the '@cite' formatting of Documenter. However, we maintain the separate 'References' sections at the bottom of each docstring that actually provide the full citation for immediate readability in the REPL and in the source code.
1 parent 24fa03e commit 148828d

File tree

7 files changed

+113
-23
lines changed

7 files changed

+113
-23
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66

77
## [Unreleased]
88

9+
### Added
10+
11+
- Added **References** sections to docstrings for immediate readability in the REPL and in the source code without needing to open the Documenter-generated website (#47, #48).
12+
913
## [0.1.1] - 2025-08-05
1014

1115
### Changed

src/core.jl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@
88
s_bandwidth(g::AbstractGraph, S) -> SBandMinimizationResult
99
s_bandwidth(L::AbstractMatrix{<:Integer}, S) -> SBandMinimizationResult
1010
11-
[TODO: Write here. Also, comment inline and cite [JP25](@cite).]
11+
[TODO: Write here. Also, comment inline and cite [JP25].]
12+
13+
# References
14+
15+
- [JP25](@cite): N. Johnston and S. Plosker. *Laplacian {−1,0,1}- and {−1,1}-diagonalizable
16+
graphs*. *Linear Algebra and its Applications* **704**, 309–39 (2025).
17+
https://doi.org/10.1016/j.laa.2024.10.016.
1218
"""
1319
function s_bandwidth(g::AbstractGraph, S::Tuple{Vararg{Integer}})
1420
_assert_graph_has_defined_s_bandwidth(g)
@@ -75,7 +81,13 @@ end
7581
has_s_bandwidth_at_most_k(g::AbstractGraph, S, k) -> SBandRecognitionResult
7682
has_s_bandwidth_at_most_k(L::AbstractMatrix{<:Integer}, S, k) -> SBandRecognitionResult
7783
78-
[TODO: Write here. Also, comment inline and cite [JP25](@cite).]
84+
[TODO: Write here. Also, comment inline and cite [JP25].]
85+
86+
# References
87+
88+
- [JP25](@cite): N. Johnston and S. Plosker. *Laplacian {−1,0,1}- and {−1,1}-diagonalizable
89+
graphs*. *Linear Algebra and its Applications* **704**, 309–39 (2025).
90+
https://doi.org/10.1016/j.laa.2024.10.016.
7991
"""
8092
function has_s_bandwidth_at_most_k(g::AbstractGraph, S::Tuple{Vararg{Integer}}, k::Integer)
8193
_assert_graph_has_defined_s_bandwidth(g)

src/eigenvector_generation.jl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,18 @@ julia> hcat(SDiagonalizability._pot_kernel_01neg_eigvecs(3)...)
102102
103103
# Notes
104104
The number of potential kernel eigenvectors (unique up to span) for an order ``n`` Laplacian
105-
matrix is given by ``(3ⁿ - 1) / 2``. See also the relevant OEIS sequence [Slo25](@cite).
105+
matrix is given by ``(3ⁿ - 1) / 2``. See also the relevant OEIS sequence [Slo25].
106106
107107
Regrettably, the implementation here is rather clunky and unidiomatic, but it is worth
108108
noting that eigenvector generation is one of two major bottlenecks in the overall
109109
*S*-bandwidth minimization algorithm. Given how much potential there is for optimization in
110110
this piece of code, we thus prioritize performance over readability in this particular case,
111111
making every effort to include inline comments wherever clarification may be needed.
112+
113+
# References
114+
115+
- [Slo25](@cite): N. J. Sloane, *a(n) = (3^n - 1)/2*. Entry A003462 (2025). Accessed:
116+
2025-05-22. https://oeis.org/A003462.
112117
"""
113118
function _pot_kernel_01neg_eigvecs(n::Integer)
114119
# Cache to avoid redundant recomputations of the `leading` vector
@@ -197,13 +202,18 @@ julia> hcat(SDiagonalizability._pot_nonkernel_01neg_eigvecs(4)...)
197202
# Notes
198203
The number of potential non-kernel eigenvectors (unique up to span) for an order ``n``
199204
Laplacian matrix is, by non-trivial combinatorial arguments, equal to the number of humps in
200-
all Motzkin paths of length ``n``. See also the relevant OEIS sequence [Deu25](@cite).
205+
all Motzkin paths of length ``n``. See also the relevant OEIS sequence [Deu25].
201206
202207
Regrettably, the implementation here is rather clunky and unidiomatic, but it is worth
203208
noting that eigenvector generation is one of two major bottlenecks in the overall
204209
*S*-bandwidth minimization algorithm. Given how much potential there is for optimization in
205210
this piece of code, we thus prioritize performance over readability in this particular case,
206211
making every effort to include inline comments wherever clarification may be needed.
212+
213+
# References
214+
215+
- [Deu25](@cite): E. Deutsch. *Number of humps in all Motzkin paths of length n*. Entry
216+
A097861 (2025). Accessed: 2025-05-22. https://oeis.org/A097861.
207217
"""
208218
function _pot_nonkernel_01neg_eigvecs(n::Integer)
209219
# Caches to avoid redundant recomputations of the `leading` and `entries` vectors

src/factories/orthogonality_factory.jl

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ Recall that an (ordered) collection of vectors ``v₁, v₂, ..., vₙ`` is said
1414
(i.e., if every pair of vectors at least ``k`` indices apart is orthogonal). This is
1515
equivalent to the vectors' Gram matrix having bandwidth at most `k`, where we define the
1616
bandwidth of a matrix ``A`` to be the minimum integer ``k ∈ \\{1, 2, …, n\\}`` such that
17-
``Aᵢⱼ = 0`` whenever ``|i - j| ≥ k`` [JP25; p. 313](@cite). (Note that many texts instead
18-
define matrix bandwidth using zero-based indexing—that is, with the condition
19-
``|i - j| > k`` [Maf14; p. 186](@cite).)
17+
``Aᵢⱼ = 0`` whenever ``|i - j| ≥ k`` [JP25; p. 313]. (Note that many texts instead define
18+
matrix bandwidth using zero-based indexing—that is, with the condition ``|i - j| > k``
19+
[Maf14; p. 186].)
2020
2121
This type is used as a template for concretely defined properties corresponding to specific
2222
values of ``k``. In the context of the overarching *S*-bandwidth algorithm, we perform a
@@ -26,6 +26,15 @@ different depth-first search for each family of values of ``k`` on our "tree" of
2626
# Interface
2727
Concrete subtypes of `KOrthogonality` **must** implement the following fields:
2828
- `k::Int`: the ``k``-orthogonality parameter. Must be a positive integer.
29+
30+
# References
31+
32+
- [JP25](@cite): N. Johnston and S. Plosker. *Laplacian {−1,0,1}- and {−1,1}-diagonalizable
33+
graphs*. *Linear Algebra and its Applications* **704**, 309–39 (2025).
34+
https://doi.org/10.1016/j.laa.2024.10.016.
35+
- [Maf14](@cite): L. O. Mafteiu-Scai. *The Bandwidths of a Matrix. A Survey of Algorithms*.
36+
*Annals of West University of Timisoara - Mathematics and Computer Science* **52**,
37+
183–223 (2014). https://doi.org/10.2478/awutm-2014-0019.
2938
"""
3039
abstract type KOrthogonality end
3140

@@ -61,7 +70,7 @@ The property of quasi-orthogonality for a collection of vectors.
6170
Recall that an (ordered) collection of vectors ``v₁, v₂, ..., vₙ`` is said to be
6271
*quasi-orthogonal* if we have the inner product ``⟨vᵢ, vⱼ⟩ = 0`` whenever ``|i - j| ≥ 2``
6372
(i.e., if every pair of vectors at least ``2`` indices apart is orthogonal). This is
64-
equivalent to the vectors' Gram matrix being tridiagonal [JP25; p. 313](@cite).
73+
equivalent to the vectors' Gram matrix being tridiagonal [JP25; p. 313].
6574
6675
# Fields
6776
- `k::Int`: the ``k``-orthogonality parameter; always necessarily ``2``.
@@ -71,6 +80,12 @@ equivalent to the vectors' Gram matrix being tridiagonal [JP25; p. 313](@cite).
7180
7281
# Constructors
7382
- `QuasiOrthogonality()`: constructs a new `QuasiOrthogonality` object with `k = 2`.
83+
84+
# References
85+
86+
- [JP25](@cite): N. Johnston and S. Plosker. *Laplacian {−1,0,1}- and {−1,1}-diagonalizable
87+
graphs*. *Linear Algebra and its Applications* **704**, 309–39 (2025).
88+
https://doi.org/10.1016/j.laa.2024.10.016.
7489
"""
7590
struct QuasiOrthogonality <: KOrthogonality
7691
k::Int

src/laplacian_s_spectra.jl

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ constructed as well.
4646
4747
# Examples
4848
Confirm that the rotation matrix by ``π/2`` radians counterclockwise is not spectrum
49-
integral (rather, it has eigenvalues ``±i`` [Joy15; p. 1](@cite)):
49+
integral (rather, it has eigenvalues ``±i`` [Joy15; p. 1]):
5050
```jldoctest
5151
julia> R = Int8.([0 -1; 1 0])
5252
2×2 Matrix{Int8}:
@@ -68,7 +68,7 @@ true
6868
```
6969
7070
Confirm that the adjacency matrix of the Petersen graph is spectrum integral, with correct
71-
eigenvalues and multiplicities of ``\\{3: 1, -2: 4, 1: 5\\}`` [Fox09; p. 2](@cite):
71+
eigenvalues and multiplicities of ``\\{3: 1, -2: 4, 1: 5\\}`` [Fox09; p. 2]:
7272
```jldoctest
7373
julia> using Graphs
7474
@@ -116,8 +116,19 @@ OrderedCollections.OrderedDict{Int64, Int64} with 3 entries:
116116
# Notes
117117
If an undirected graph with integer edge weights is ``\\{-1, 0, 1\\}``-diagonalizable (or,
118118
more restrictively, ``\\{-1, 1\\}``-diagonalizable), then its Laplacian matrix has integer
119-
eigenvalues [JP25; p. 312](@cite). Hence, validating Laplacian integrality serves as a
120-
useful screening step in this package's principal *S*-bandwidth minimization algorithm.
119+
eigenvalues [JP25; p. 312]. Hence, validating Laplacian integrality serves as a useful
120+
screening step in this package's principal *S*-bandwidth minimization algorithm.
121+
122+
# References
123+
124+
- [Fox09](@cite): J. Fox. *Lecture 19: The Petersen graph and Moore graphs*. Lecture notes,
125+
MAT 307: Combinatorics (2009). Accessed: 2025-07-25.
126+
https://math.mit.edu/~fox/MAT307.html.
127+
- [Joy15](@cite): D. Joyce. *Rotations and complex eigenvalues*. Lecture notes, Math 130:
128+
Linear Algebra (2015). http://aleph0.clarku.edu/~ma130/complexeigen.pdf.
129+
- [JP25](@cite): N. Johnston and S. Plosker. *Laplacian {−1,0,1}- and {−1,1}-diagonalizable
130+
graphs*. *Linear Algebra and its Applications* **704**, 309–39 (2025).
131+
https://doi.org/10.1016/j.laa.2024.10.016.
121132
"""
122133
function check_spectrum_integrality(A::AbstractMatrix{<:Integer})
123134
A_copy = Matrix{Int}(A) # Avoid shared mutability and cast to `Matrix{Int}`

src/types.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,14 @@ eigenvalues are indeed all integers. (Otherwise, the associated field is simply
173173
# Notes
174174
If an undirected graph with integer edge weights is ``\\{-1, 0, 1\\}``-diagonalizable (or,
175175
more restrictively, ``\\{-1, 1\\}``-diagonalizable), then its Laplacian matrix has integer
176-
eigenvalues [JP25; p. 312](@cite). Hence, validating Laplacian integrality serves as a
177-
useful screening step in this package's principal *S*-bandwidth minimization algorithm.
176+
eigenvalues [JP25; p. 312]. Hence, validating Laplacian integrality serves as a useful
177+
screening step in this package's principal *S*-bandwidth minimization algorithm.
178+
179+
# References
180+
181+
- [JP25](@cite): N. Johnston and S. Plosker. *Laplacian {−1,0,1}- and {−1,1}-diagonalizable
182+
graphs*. *Linear Algebra and its Applications* **704**, 309–39 (2025).
183+
https://doi.org/10.1016/j.laa.2024.10.016.
178184
"""
179185
struct SpectrumIntegralResult{T<:Union{Nothing,OrderedDict{Int,Int}}}
180186
matrix::AbstractMatrix{<:Integer}

src/utils.jl

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ an SVD), while the pivots are used to extract a spanning set of independent colu
3939
4040
The rank-revealing Businger–Golub QR algorithm is used for the pivoting strategy, appending
4141
the "most independent" column with respect to the current set of pivots at each step via
42-
Householder transformations [BG65; pp. 269--70](@cite).
42+
Householder transformations [BG65; pp. 269--70].
4343
4444
# Arguments
4545
- `A::AbstractMatrix{T<:Integer}`: the matrix whose independent columns to extract.
@@ -75,9 +75,9 @@ julia> SDiagonalizability._extract_independent_cols(A)
7575
Since we already need a pivoted QR decomposition to identify independent columns of `A` (or,
7676
rather, to order the columns in such a way that the first `rank(A)` ones are guaranteed to
7777
be independent), it makes sense to use data from the resulting factorization object to
78-
compute the rank of `A` rather than compute a separate SVD. We thus count the nonzero scaling
79-
coefficients—that is, the diagonal entries of the `R` matrix in `A = QR`—to determine the
80-
rank, similarly to how we count the nonzero singular values in an SVD.
78+
compute the rank of `A` rather than compute a separate SVD. We thus count the nonzero
79+
scaling coefficients—that is, the diagonal entries of the `R` matrix in `A = QR`—to
80+
determine the rank, similarly to how we count the nonzero singular values in an SVD.
8181
8282
It is worth noting that we manually specify a higher relative tolerance for this rank
8383
computation. Further discussion can be found in the [`_rank_rtol`](@ref) documentation, but
@@ -87,7 +87,18 @@ tall-and-skinny and short-and-fat matrices (precisely the type we expect to enco
8787
dealing with all ``\\{-1, 0, 1\\}``-eigenvectors of a Laplacian matrix, which is the
8888
intended use case of this helper function in this package). Our replacement tolerance, on
8989
the other hand, is a widely accepted standard in numerical analysis which uses the maximum
90-
dimension instead [PTVF07; p. 795](@cite).
90+
dimension instead [PTVF07; p. 795].
91+
92+
# References
93+
94+
- [BG65](@cite): P. Businger and G. H. Golub. *Linear Least Squares Solutions by Householder
95+
Transformations*. *Numerische Mathematik* **7**, 269–76 (1965).
96+
https://doi.org/10.1007/BF01436084.
97+
98+
- [PTVF07](@cite): W. H. Press, S. A. Teukolsky, W. T. Vetterling and B. P. Flannery.
99+
*Numerical Recipes: The Art of Scientific Computing*. 3rd Edition (Cambridge University
100+
Press, Cambridge, UK, 2007). ISBN: 978-0-521-88068-8.
101+
https://dl.acm.org/doi/10.5555/1403886.
91102
"""
92103
function _extract_independent_cols(A::AbstractMatrix{<:Integer})
93104
F = qr(A, ColumnNorm())
@@ -156,7 +167,7 @@ Matrix has nonzero row sums; cannot be an (undirected) Laplacian
156167
157168
Both the in-degree and out-degree Laplacian matrices of this random tournament digraph have
158169
zero row sums but are not symmetric, so they fail the check. (These are the two standard
159-
ways of extending the concept of the Laplacian to directed graphs [VL20; p. 196](@cite).)
170+
ways of extending the concept of the Laplacian to directed graphs [VL20; p. 196].)
160171
```jldoctest
161172
julia> using Graphs
162173
@@ -204,6 +215,12 @@ At first blush, it may seem as though the choice of `DomainError` over something
204215
this is informed by the simple *ad hoc* use of this function to validate inputs for other
205216
functions requiring Laplacian matrices. Certainly, this function is never meant to be
206217
publicly exposed on its own.
218+
219+
# References
220+
221+
- [VL20](@cite): J. J. Veerman and R. Lyons. *A Primer on Laplacian Dynamics in Directed
222+
Graphs*. *Nonlinear Phenomena in Complex Systems* **23**, 196–206 (2020).
223+
https://doi.org/10.33581/1561-4085-2020-23-2-196-206.
207224
"""
208225
function _assert_matrix_is_undirected_laplacian(L::AbstractMatrix{<:Integer})
209226
if !issymmetric(L)
@@ -266,11 +283,26 @@ type of `A` when `eltype(A)` is not an `AbstractFloat`.
266283
`LinearAlgebra.rank`'s default `rtol` of `min(m,n) * ϵ` for computing the rank of an
267284
``m×n`` matrix may result in overestimating rank when ``|m - n| ≫ 0``, since condition
268285
number (which determines how numerically stable SVD and QRD are) grows with both dimensions
269-
[CD05; p. 603](@cite). Given that we often deal with short-and-fat matrices in this package
286+
[CD05; p. 603]. Given that we often deal with short-and-fat matrices in this package
270287
(particularly when processing all ``\\{-1, 0, 1\\}``-eigenvectors of a Laplacian matrix), we
271288
turn instead to the same relative tolerance used by NumPy's and MATLAB's rank
272-
functions—`max(m,n) * ϵ` [Num25, MAT25](@cite). (Indeed, this is a widely adopted standard
273-
across the field of numerical analysis [PTVF07; p. 795](@cite).)
289+
functions—`max(m,n) * ϵ` [Num25, MAT25]. (Indeed, this is a widely adopted standard across
290+
the field of numerical analysis [PTVF07; p. 795].)
291+
292+
# References
293+
294+
- [CD05](@cite): Z. Chen and J. Dongarra. *Condition Numbers of Gaussian Random Matrices*.
295+
*SIAM Journal on Matrix Analysis and Applications* **27**, 603–20 (2005).
296+
https://doi.org/10.1137/040616413.
297+
- [MAT25](@cite): MATLAB Developers, *rank*. MATLAB reference documentation – R2025a (2025).
298+
Accessed: 2025-05-29. https://www.mathworks.com/help/matlab/ref/rank.html.
299+
- [Num25](@cite): NumPy Developers, *numpy.linalg.matrix_rank*. NumPy reference
300+
documentation – v2.2 (2025). Accessed: 2025-05-22.
301+
https://numpy.org/doc/stable/reference/generated/numpy.linalg.matrix_rank.html.
302+
- [PTVF07](@cite): W. H. Press, S. A. Teukolsky, W. T. Vetterling and B. P. Flannery.
303+
*Numerical Recipes: The Art of Scientific Computing*. 3rd Edition (Cambridge University
304+
Press, Cambridge, UK, 2007). ISBN: 978-0-521-88068-8.
305+
https://dl.acm.org/doi/10.5555/1403886.
274306
"""
275307
function _rank_rtol(A::AbstractMatrix{T}) where {T}
276308
return maximum(size(A)) * eps(LinearAlgebra.eigtype(T))

0 commit comments

Comments
 (0)