LCOV - code coverage report
Current view: top level - src/connectivity - graphlaplacian.jl (source / functions) Hit Total Coverage
Test: on branch nothing Lines: 33 33 100.0 %
Date: 2025-07-10 13:12:25 Functions: 0 0 -

          Line data    Source code
       1             : """
       2             :     L = umbrella(mesh[; symmetric=true, typ=Float64])
       3             : 
       4             : Get uniform Laplacian (Leif Kobbelt's *umbrella operator*) either as
       5             : `symmetric` *sparse* matrix (i.e., with vertex [`degree`](@ref)s on
       6             : matrix diagonal) or with row weighting by inverse vertex degrees
       7             : (i.e., with unit-diagonal). The optional keyword argument `typ`
       8             : determines the `SparseMatrix{typ}`.
       9             : 
      10             : !!! note
      11             :     This implementation does *not* treat the boundary as a
      12             :     univariate polygon.
      13             : 
      14             : See also [`graphlaplacian`](@ref), [`adjacencymatrix`](@ref)
      15             : """
      16           4 : function umbrella(mesh::Mesh; symmetric::Bool=true, typ=Float64)
      17           2 :     A = adjacencymatrix(mesh; one=typ(1))
      18           2 :     V = Diagonal(vec(sum(A; dims=2)))
      19             : 
      20           2 :     U = A - V
      21             : 
      22           2 :     if symmetric
      23           1 :         U
      24             :     else
      25           1 :         V \ U
      26             :     end
      27             : end
      28             : 
      29             : abstract type GraphLaplacianEdgeType end
      30           4 : struct Undirected <: GraphLaplacianEdgeType end
      31           1 : struct InEdges <: GraphLaplacianEdgeType end
      32           1 : struct OutEdges <: GraphLaplacianEdgeType end
      33             : 
      34             : abstract type GraphLaplacianMode end
      35           4 : struct Plain <: GraphLaplacianMode end
      36           1 : struct Normalized <: GraphLaplacianMode end
      37           1 : struct NormalizedSymmetric <: GraphLaplacianMode end
      38             : 
      39             : """
      40             :     L = graphlaplacian(mesh[; edges = Undirected(),
      41             :                               mode = Plain(),
      42             :                               typ=Float64)
      43             : 
      44             : Get Graph Laplacian `L` with
      45             : 
      46             : - `edges = Undirected()`: ignore edge orientation,
      47             : - `edged ∈ [InEdges(), OutEdges()]`: consider only given orientation.
      48             : 
      49             : and
      50             : 
      51             : - `mode = Plain()` graph Laplacian ``D - A`` (for adjacency matrix ``A``
      52             :    and diagonal matrix with vertex [`degree`](@ref)s ``D``, equals
      53             :    `-umbrella(mesh; symmetric=true)`),
      54             : - `mode = Normalized()` normalized graph Laplacian ``D^{-1}\\,(D-A)``
      55             :   (equals `-umbrella(mesh; symmetric=false)`),
      56             : - `mode = NormalizedSymmetric()` symmetrically normalized graph Laplacian
      57             :   ``I\\,-\\,D^{-\\tfrac{1}{2}}\\,(D-A)\\,D^{-\\tfrac{1}{2}}``.
      58             : 
      59             : See also [`umbrella`](@ref), [`adjacencymatrix`](@ref)
      60             : """
      61          12 : function graphlaplacian(mesh::Mesh;
      62             :                         edges::E=Undirected(), mode::M=Plain(),
      63             :                         typ=Float64) where {E<:GraphLaplacianEdgeType,
      64             :                                             M<:GraphLaplacianMode}
      65           6 :     A, D = _graphlaplacian(mesh, edges, typ)
      66           6 :     _graphlaplacianmode(A, D, mode)
      67             : end
      68             : 
      69           4 : function _graphlaplacian(mesh::Mesh, ::Undirected, typ)
      70           4 :     A = adjacencymatrix(mesh; one=one(typ))
      71           4 :     D = Diagonal(vec(sum(A; dims=2)))
      72             : 
      73           4 :     A, D
      74             : end
      75             : 
      76           1 : function _graphlaplacian(mesh::Mesh, ::OutEdges, typ)
      77           1 :     A = adjacencymatrix(mesh; one=one(typ), boundary=false)
      78           1 :     D = Diagonal(vec(sum(A, dims=2)))
      79           1 :     A, D
      80             : end
      81             : 
      82           1 : function _graphlaplacian(mesh::Mesh, ::InEdges, typ)
      83           1 :     A = adjacencymatrix(mesh; one=one(typ), boundary=false)'
      84             : 
      85           1 :     D = Diagonal(vec(sum(A, dims=1)))
      86           1 :     A, D
      87             : end
      88             : 
      89           4 : _graphlaplacianmode(A, D, ::Plain) = D - A
      90             : 
      91           1 : _graphlaplacianmode(A, D, ::Normalized) = D \ (D - A)
      92             : 
      93           1 : function _graphlaplacianmode(A, D, ::NormalizedSymmetric)
      94           2 :     D2 = Diagonal(1 ./ sqrt.(diag(D)))
      95           1 :     I - D2 * A * D2
      96             : end

Generated by: LCOV version 1.16