Description
I noticed that when converting an undirected and unweighted graph from NetworkX, each self loop is represented by 1 (and not 2) on the diagonal. Example:
g = nx.Graph([(0,1), (1,1)])
gb.io.from_networkx(g)
The result is this matrix:
0 1
1 1
I would have expected:
0 1
1 2
Adding self-loops once to the diagonal is not incorrect per se, but it tends to be mathematically inconvenient as many identities that people expect to hold will be broken. For example, do we consider an undirected graph to be equivalent to a directed one where each undirected edge was replaced by two reciprocal directed ones? That would no longer be the case. Are the degrees obtained as row or column sums? That does not work. Is the number of edges in an undirected graph half the sum of the matrix elements? No. Consider a random walk process on the graph, which is the underlying model for many network analysis concepts such as PageRank. Can the walker traverse a self-loop in both directions? Adding one to the diagonal implies no.
One can certainly build a consistent system while considering self-loops only once in undirected graphs, but the outcome tends to be a bit less intuitive, and a bit harder to understand for people who just want to do network analysis. Several of the network analysis libraries are unfortunately inconsistent: some analysis functions implicitly consider self-loops once, some others twice. Thus be very careful with following others' example.
I would suggest considering this choice very carefully, and making sure that the systems you design (e.g. graphblas-algorithms) behave consistently and intuitively.