-
-
Notifications
You must be signed in to change notification settings - Fork 206
Description
What is the feature or improvement you would like to see?
Nice to have: function to calculate the vertex-edge incidence matrix of a graph.
20240118 - Added argument weights = NULL
20240119 - Added example graph, directed, multiple, weighted.
20240123 - Added example graph with self-loop.
Description
The vertex-edge incidence matrix of a graph.
Usage
as_ve_incidence_matrix <- function(
graph
, mode = c("all", "out", "in")
, loops
, multiple
, weights = NULL
, names = FALSE
, attr = "label"
, sparse = igraph_opt("sparsematrices")
)
Depending on personal taste, we can choose one of the following alternatives:
- as_vertex_edge_incidence_matrix()
- as_veincidence_matrix(), as in as_biadjacency_matrix().
- vertex_edge_incidence_matrix(), as in laplacian_matrix.
- ve_incidence_matrix(), shorter version.
- …
Arguments
graph
- simple or multi-edge
- directed, undirected
- weighted, unweighted
- named, unnamed
- with or without loops
- sparse, non-sparse
mode
- as in incident(), distances().
loops
- As in igraph Reference Manual.
- igraph_adjlist_init_empty — Initializes an empty adjacency list. p. 187.
multiple
- As in igraph Reference Manual.
weights
- as in distances(), cluster_leiden().
For example, Wikipedia, wiki/Incidence_matrix, chapter Weighted graphs.
names
- If NA, ignore names.
- If NULL, copy vertex name and edge label from graph if present, to dimnames.
- If matrix, then copy to dimnames.
attr
- name of the edge attr to be used for colnames of the matrix, default is "label".
sparse
- as in laplacian_matrix()
Details
This function calculates the vertex-edge incidence matrix B of graph g.
If g is undirected, Bxe = 1 when vertex x is incident with edge e, 0 otherwise.
If g is directed, Bxe = −1,1,0 when vertex x is the head of edge e, the tail of e, or not on e, respectively.
If weights are taken into account, then -1, 1 becomes -w, w, where w is the weight of edge e.
Value
A possibly sparse matrix B with rows indexed by the vertices and columns indexed by the edges.
See Also
The function laplacian_matrix() computes the out-degree Laplacian matrix. To allow the calculation of a symmetric Laplacian matrix, the function should be modified to support mode="all", in particular to ignore the orientation of edges. Currently, a workaround is to convert the graph to its undirected version.
The function as_adjacency_matrix() includes weights using attr = "weight".
See also Github/igraph/rigraph/issue #906, as_adjacency_matrix() should use weights instead of attr parameter.
See also Github/igraph/rigraph/issues #1125, Treat self-loops in igraph functions consistently.
Examples
library(igraph)
g1 <- make_ring(3, circular=FALSE) # Undirected, simple.
g2 <- graph(c(1,2,1,2,2,3), directed=FALSE ) # Undirected, multi edge.
g2w <- graph(c(1,2,2,3), directed=FALSE ) # Undirected
E(g2w)$weight <- c(2,1); E(g2w)$label <- E(g2w)$weight # Weighted.
g3 <- make_ring(3,circular=FALSE, directed=TRUE) # Directed, simple.
g4 <- graph(c(1,2,1,2,2,3) ) # Directed, multi edge.
g4w<- g4; # Directed, multi edge.
E(g4w)$weight<- c(2,3, 5); E(g4w)$label<- E(g4w)$weight # Weighted.
# Named graph, undirected. From wiki/Incidence_matrix.
g5 <- graph_from_literal(1-2, 1-3, 1-4, 3-4)
E(g5)$label <- paste0("e", seq_len(gsize(g5)) )
# Named graph, directed, From /wiki/Directed_graph (-B).
g6 <- graph_from_literal(a-+b-+c-+a, a-+d, simplify=FALSE)
g6$name <- "g6"; E(g6)$label <- c("1", "2", "3", "4")
# Undirected graph with loops, e.g. edge incident with a single vertex.
# An undirected loop adds two or one to the degree of its vertex (depending on parameters).
g7 <- graph(c(1,1,1,1,1,2,1,2), directed=FALSE)
# A directed loop adds 0 to the degree of its vertex.
g8 <- graph(c(1,1,1,1,1,2,1,2), directed=TRUE)
# Print incidence matrices.
for (g in list(g2, g4w, g6, g7, g8) )
{cat("\n");print(g); print(as_ve_incidence_matrix(g, weights=NULL))}
# Expected output.
# IGRAPH 3371287 U--- 3 3 --
# + edges from 3371287:
# [1] 1--2 1--2 2--3
# [,1] [,2] [,3]
# [1,] 1 1 0
# [2,] 1 1 1
# [3,] 0 0 1
#
# IGRAPH 337f2fd D-W- 3 3 --
# + attr: weight (e/n), label (e/n)
# + edges from 337f2fd:
# [1] 1->2 1->2 2->3
# [,1] [,2] [,3]
# [1,] -2 -3 0
# [2,] 2 3 -5
# [3,] 0 0 5
#
# IGRAPH 33949a0 DN-- 4 4 -- g6
# + attr: name (g/c), name (v/c), label (e/c)
# + edges from 33949a0 (vertex names):
# [1] a->b b->c c->a a->d
# 1 2 3 4
# a -1 0 1 -1
# b 1 -1 0 0
# c 0 1 -1 0
# d 0 0 0 1
#
# IGRAPH 33a118b U--- 2 4 --
# + edges from 33a118b:
# [1] 1--1 1--1 1--2 1--2
# [,1] [,2] [,3] [,4]
# [1,] 2 2 1 1
# [2,] 0 0 1 1
#
# IGRAPH 33a8e26 D--- 2 4 --
# + edges from 33a8e26:
# [1] 1->1 1->1 1->2 1->2
# [,1] [,2] [,3] [,4]
# [1,] 0 0 -1 -1
# [2,] 0 0 1 1
The following relationships apply:
Let
- g be a graph without loops.
- L is the Laplacian matrix of graph g. Q is the signless Laplacian matrix.
- B is the unweighted vertex-edge incidence matrix.
- Bw is the (un)weighted matrix, depending on whether or not weights are taken into account.
- W is the diagonal matrix containing the edge weights, or ones if weights are not considered.
Then
- Bw = BW.
- Q = BwBT, when g is undirected.
- L = BwBT, when g is directed.
References
- igraph Reference Manual, https://igraph.org/c/pdf/latest/igraph-docs.pdf
- A. Brouwer, and W. Haemers, "Spectra of graphs", monograph, https://www.win.tue.nl/~aeb/2WF02/spectra.pdf, p11.