Many of the graph distances here are essentially two-step processes:
- calculate some feature vector for each graph
- calculate a distance between those feature vectors
So, DegreeDivergence computes the degree histograms and NetSimile constructs a vector of "signatures," then DegreeDivergence computes the JSD and NetSimile computes Canberra distance. The choice here is sometimes principled, sometimes arbitrary.
It would be preferable, to make the package flexible, to make these slightly more explicitly distinct. In practice this would look a lot like how the thresholding issue for graph reconstructions was handled (#38).
A conceptual illustration using DegreeDivergence:
class DegreeDivergence(BaseDistance):
def dist(self, G1, G2, measure_type='jsd'):
# get the degrees
# from degree sequences to degree histograms
dist = measure(p1, p2, measure_type)
where measure is basically a wrapper around things like np.linalg.norm, sp.stats.wasserstein_distance, or our JSD function (#165).
Many of the graph distances here are essentially two-step processes:
So,
DegreeDivergencecomputes the degree histograms andNetSimileconstructs a vector of "signatures," thenDegreeDivergencecomputes the JSD andNetSimilecomputes Canberra distance. The choice here is sometimes principled, sometimes arbitrary.It would be preferable, to make the package flexible, to make these slightly more explicitly distinct. In practice this would look a lot like how the thresholding issue for graph reconstructions was handled (#38).
A conceptual illustration using
DegreeDivergence:where
measureis basically a wrapper around things likenp.linalg.norm,sp.stats.wasserstein_distance, or our JSD function (#165).