GraphFragment (int startNode, Function<? super Integer, ? extends List<Integer>> getNextNodes, Function<? super Integer, ? extends List<Integer>> getPrevNodes, Set<Integer> thisNodeCantBeInMiddle, boolean isDown) { Set<Integer> blackNodes = new HashSet<>(); blackNodes.add(startNode); Set<Integer> grayNodes = new HashSet<>(getNextNodes.fun(startNode)); int endNode = -1; while (blackNodes.size() < SHORT_FRAGMENT_MAX_SIZE) { int nextBlackNode = -1; for (int grayNode : grayNodes) { if (blackNodes.containsAll(getPrevNodes.fun(grayNode))) { nextBlackNode = grayNode; break; } } if (nextBlackNode == -1) return null; if (grayNodes.size() == 1) { endNode = nextBlackNode; break; } List<Integer> nextGrayNodes = getNextNodes.fun(nextBlackNode); if (nextGrayNodes.isEmpty() || thisNodeCantBeInMiddle.contains(nextBlackNode)) return null; blackNodes.add(nextBlackNode); grayNodes.remove(nextBlackNode); grayNodes.addAll(nextGrayNodes); } if (endNode != -1) { return isDown ? GraphFragment.create(startNode, endNode) : GraphFragment.create(endNode, startNode); } else { return null; } }