2

My code:

import org.jgrapht.graph.DirectedAcyclicGraph;
// ...
private DirectedAcyclicGraph<String, DefaultEdge> graph = new DirectedAcyclicGraph<>(DefaultEdge.class);
// ...
graph.addVertex("x");
graph.addVertex("y");
// ...
graph.addEdge("x", "y");

After constructing the graph, how can I get a set of all the roots (vertices with no incoming edges) and of all leaves (vertices with no outgoing edges)

Mugen
  • 8,301
  • 10
  • 62
  • 140

3 Answers3

3

The following is working, but doesn't strike me as most efficient.

// leaves:
graph.vertexSet().stream()
                .filter(key -> graph.outgoingEdgesOf(key).size() == 0)
                .forEach(key -> doLeavesStuff(key));

// roots:
graph.vertexSet().stream()
                .filter(key -> graph.incomingEdgesOf(key).size() == 0)
                .forEach(key -> doRootsStuff(key));
Mugen
  • 8,301
  • 10
  • 62
  • 140
1

Shouldn't it be:

// leaves:
graph.vertexSet().stream().filter(
    key -> graph.incomingEdgesOf(key).size() == 0
).forEach(
    key -> doLeavesStuff(key)
);

// roots:
graph.vertexSet().stream().filter(
    key -> graph.outgoingEdgesOf(key).size() == 0
).forEach(
    key -> doRootsStuff(key)
);

intead?

  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-ask). – Community Sep 20 '21 at 11:21
  • yes, you're right, I was storing the keys in an additional map and therefore used `keySet`. will edit my answer. next time you can just leave a comment :) – Mugen Sep 21 '21 at 06:49
0

I used

class DAG extends jgrapht.graph.DirectedAcyclicGraph <Node,Edge> {

   Collection <Node> nodes = collected_for_additional_purposes ();

   private int countRoots () {
      int count = 0;
      for (final Node node : nodes) {
         if (inDegreeOf (node) == 0) {
            count++;
         }
      }
      return count;
   }
}

It's akin to stream used in accepted answer and one could use an iterator too, but the difference here is using inDegreeOf (aVertex). Similarly outDegreeOf would work too.

As an aside, I tried doing the following, but count++ generated compiler error "Local variable count defined in an enclosing scope must be final or effectively final". I'm wondering what a clean, expressive inline syntax might look like.

private int countRoots () {
   int count = 0;
   nodes.forEach (node -> {
      if (inDegreeOf (node) == 0) {
         count++;
      }
   });
   return count;
}

https://jgrapht.org/javadoc-1.0.0/org/jgrapht/graph/AbstractBaseGraph.html#inDegreeOf-V-

Alan
  • 716
  • 5
  • 15