pnevyk / gryf

Graph data structure library aspiring to be convenient, versatile, correct and performant.
MIT License
69 stars 1 forks source link

Semantics of neighbors iterator for undirected self-loops #55

Closed pnevyk closed 1 year ago

pnevyk commented 1 year ago

It feels inefficient and counter-intuitive to yield a self-loop edge twice when iterating over neighbors of a vertex. However, a self-loop in undirected graphs contributes 2 to a vertex's degree, for the two ends of the edge. So yielding the edge only once breaks the current default implementation of degree calculation on Neighbors trait. I think it would be fine to remove the default implementations and require ones from the storage implementer.

On top of that, should this be a specified behavior that is required to be followed by any storage? Because if it is left to be implementation-specific, this would probably cause quite a hard time for correct implementation of degree for Stable graph adapter, where it would not be clear if a self-loop edge should be counted twice or not (depending on whether the underlying iterator yields the self-loop twice or not).

Is there a merit in requiring yielding a self-loop twice always? This would keep the default implementation of degree calculation trivial, but is it worthy? Are there any other arguments in favor?

pnevyk commented 1 year ago

Another argument for requirement on storages to always report self-loop just once is that the default implementation of degree can be adapted such that it checks for self-loops and adds 2 instead of 1 to the final count.

pnevyk commented 1 year ago

It is now required to yield self-loops in undirected graph only once.