2

Suppose I have the following graph:

(graph, nodeFromVertex, vertexFromKey) = graphFromEdges [("a", 'a', ['b']), ("b", 'b', ['c']), ("c", 'c', []), ("d", 'd', ['b'])]

This is the visual:

enter image description here

I want a way to figure out the vertices that do not have any outgoing edges.

In this case it is only c

I assume the way to find this is manually recurse until you find a vertex that has no connections. But I am not sure how to recurse here...

The Haskell graph docs don't really say...

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
K Split X
  • 3,405
  • 7
  • 24
  • 49

2 Answers2

2

The Graph is an Array Vertex [Vertex]. You can index it with a Vertex (a 0 based Int index), and get back a list of the successor vertices. You can get a list of vertices with no successors like this (assume Data.Array is imported):

vs = [v | (v, []) <- Data.Array.assocs graph]

This list comprehension selects the indices of elements with an empty list of successors.

The vertices can be mapped to nodes with the nodeFromVertex function.

pat
  • 12,587
  • 1
  • 23
  • 52
2

You can use outdegree to get an array of all the vertices' count of outgoing edges:

Prelude Data.Graph Data.Array> outdegree graph
array (0,3) [(0,1),(1,1),(2,0),(3,1)]

The value of each element in the array is the number of outgoing edges. If you want to filter the array, you can turn it into an association list:

Prelude Data.Graph Data.Array> assocs $ outdegree graph
[(0,1),(1,1),(2,0),(3,1)]

and then filter it. Since you're interested in the vertices that have no outgoing edges, you can filter on those where the value (the second element) in the association list is 0:

Prelude Data.Graph Data.Array> filter ((0 ==) . snd) $ assocs $ outdegree graph
[(2,0)]

If you want a list of nodes, you can map that filtered association list using nodeFromVertex:

Prelude Data.Graph Data.Array> l = filter ((0 ==) . snd) $ assocs $ outdegree graph
Prelude Data.Graph Data.Array> fmap (nodeFromVertex . fst) l
[("c",'c',"")]
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • Hey Mark, pretty sure there is a more orthodox way of getting a hold of you, but could you `Maybe` take a stab at this one - https://stackoverflow.com/questions/71243589/what-is-this-more-general-almost-traversal-operation ? Eagerly `await`ing your response... – Bondolin Feb 23 '22 at 20:26
  • @Bondolin Indeed, there's plenty of contact information on my Stack Overflow profile. (It looks like you already had some good responses on that question.) – Mark Seemann Feb 24 '22 at 06:37