private Group build(long start) { TLongSet group = new TLongHashSet(); group.add(start); TLongSet left = new TLongHashSet(); left.addAll(graph.getEdgesOut(start)); while (!left.isEmpty()) { long next = any(left); if (group.contains(next)) { continue; } group.add(next); Set<Long> out = graph.getEdgesOut(next); left.addAll(out); } return new Group(start, group); }
public List<Group> buildGroupsDirected() { List<Group> groups = new LinkedList<>(); // First determine 'start' relations, i.e. relations without incoming // edges in the relation graph TLongSet starts = new TLongHashSet(); Collection<Long> ids = graph.getNodes(); for (long id : ids) { if (graph.getEdgesIn(id).isEmpty()) { starts.add(id); } } // Build sub-graphs reachable from 'start' relations logger.debug("Number of start relations: " + starts.size()); for (long start : starts.toArray()) { groups.add(build(start)); } // In case of circles within the relation graph that are not reachable // from any start relation, there may be some relations left, that have // not been put into groups yet. TLongSet remaining = new TLongHashSet(); remaining.addAll(ids); for (Group group : groups) { remaining.removeAll(group.getRelationIds()); } if (remaining.size() > 0) { logger.debug("remaining: " + remaining.size()); while (!remaining.isEmpty()) { long id = any(remaining); TLongSet reachable = reachable(graph, id); remaining.removeAll(reachable); long lowest = IdUtil.lowestId(reachable); groups.add(new Group(lowest, reachable)); } } return groups; }