44import com .google .common .graph .Graph ;
55import com .google .common .graph .GraphBuilder ;
66import com .google .common .graph .MutableGraph ;
7- import com .mojang .datafixers .util .Pair ;
7+ import it .unimi .dsi .fastutil .objects .AbstractObject2IntMap ;
8+ import it .unimi .dsi .fastutil .objects .Object2IntMap ;
9+ import it .unimi .dsi .fastutil .objects .Object2IntOpenHashMap ;
10+ import it .unimi .dsi .fastutil .objects .Object2ObjectMap ;
11+ import it .unimi .dsi .fastutil .objects .Object2ObjectOpenHashMap ;
12+ import it .unimi .dsi .fastutil .objects .ObjectArrayList ;
13+ import it .unimi .dsi .fastutil .objects .ObjectList ;
14+ import it .unimi .dsi .fastutil .objects .ObjectOpenHashSet ;
15+ import it .unimi .dsi .fastutil .objects .ObjectSet ;
816import java .util .ArrayDeque ;
9- import java .util .ArrayList ;
10- import java .util .HashMap ;
11- import java .util .HashSet ;
12- import java .util .List ;
13- import java .util .Map ;
1417import java .util .Set ;
1518import java .util .function .BiConsumer ;
1619import java .util .function .Consumer ;
@@ -32,21 +35,21 @@ public class JohnsonSimpleCycles<V> {
3235 private final Graph <V > graph ;
3336
3437 // The main state of the algorithm.
35- private Consumer <List <V >> cycleConsumer = null ;
38+ private Consumer <ObjectList <V >> cycleConsumer = null ;
3639 private BiConsumer <V , V > cycleVertexSuccessorConsumer = null ; // Paper
3740 private V [] iToV = null ;
38- private Map < V , Integer > vToI = null ;
39- private Set <V > blocked = null ;
40- private Map <V , Set <V >> bSets = null ;
41+ private Object2IntMap < V > vToI = null ;
42+ private ObjectSet <V > blocked = null ;
43+ private Object2ObjectMap <V , ObjectSet <V >> bSets = null ;
4144 private ArrayDeque <V > stack = null ;
4245
4346 // The state of the embedded Tarjan SCC algorithm.
44- private List < Set <V >> foundSCCs = null ;
47+ private ObjectList < ObjectSet <V >> foundSCCs = null ;
4548 private int index = 0 ;
46- private Map < V , Integer > vIndex = null ;
47- private Map < V , Integer > vLowlink = null ;
49+ private Object2IntMap < V > vIndex = null ;
50+ private Object2IntMap < V > vLowlink = null ;
4851 private ArrayDeque <V > path = null ;
49- private Set <V > pathSet = null ;
52+ private ObjectSet <V > pathSet = null ;
5053
5154 /**
5255 * Create a simple cycle finder for the specified graph.
@@ -64,8 +67,8 @@ public JohnsonSimpleCycles(Graph<V> graph) {
6467 *
6568 * @return The list of all simple cycles. Possibly empty but never <code>null</code>.
6669 */
67- public List < List <V >> findAndRemoveSimpleCycles () {
68- List < List <V >> result = new ArrayList <>();
70+ public ObjectList < ObjectList <V >> findAndRemoveSimpleCycles () {
71+ ObjectList < ObjectList <V >> result = new ObjectArrayList <>();
6972 findSimpleCycles (result ::add , (v , s ) -> ((MutableGraph <V >) graph ).removeEdge (v , s )); // Paper
7073 return result ;
7174 }
@@ -75,7 +78,7 @@ public List<List<V>> findAndRemoveSimpleCycles() {
7578 *
7679 * @param consumer Consumer that will be called with each cycle found.
7780 */
78- public void findSimpleCycles (Consumer <List <V >> consumer ,
81+ public void findSimpleCycles (Consumer <ObjectList <V >> consumer ,
7982 BiConsumer <V , V > vertexSuccessorConsumer ) // Paper
8083 {
8184 if (graph == null ) {
@@ -87,10 +90,10 @@ public void findSimpleCycles(Consumer<List<V>> consumer,
8790 int startIndex = 0 ;
8891 int size = graph .nodes ().size ();
8992 while (startIndex < size ) {
90- Pair <Graph <V >, Integer > minSCCGResult = findMinSCSG (startIndex );
93+ Object2IntMap . Entry <Graph <V >> minSCCGResult = findMinSCSG (startIndex );
9194 if (minSCCGResult != null ) {
92- startIndex = minSCCGResult .getSecond ();
93- Graph <V > scg = minSCCGResult .getFirst ();
95+ startIndex = minSCCGResult .getIntValue ();
96+ Graph <V > scg = minSCCGResult .getKey ();
9497 V startV = toV (startIndex );
9598 for (V v : scg .successors (startV )) {
9699 blocked .remove (v );
@@ -106,7 +109,7 @@ public void findSimpleCycles(Consumer<List<V>> consumer,
106109 clearState ();
107110 }
108111
109- private Pair <Graph <V >, Integer > findMinSCSG (int startIndex ) {
112+ private Object2IntMap . Entry <Graph <V >> findMinSCSG (int startIndex ) {
110113 /*
111114 * Per Johnson : "adjacency structure of strong component $K$ with least vertex in subgraph
112115 * of $G$ induced by $(s, s + 1, n)$". Or in contemporary terms: the strongly connected
@@ -115,12 +118,12 @@ private Pair<Graph<V>, Integer> findMinSCSG(int startIndex) {
115118 */
116119 initMinSCGState ();
117120
118- List < Set <V >> foundSCCs = findSCCS (startIndex );
121+ ObjectList < ObjectSet <V >> foundSCCs = findSCCS (startIndex );
119122
120123 // find the SCC with the minimum index
121124 int minIndexFound = Integer .MAX_VALUE ;
122- Set <V > minSCC = null ;
123- for (Set <V > scc : foundSCCs ) {
125+ ObjectSet <V > minSCC = null ;
126+ for (ObjectSet <V > scc : foundSCCs ) {
124127 for (V v : scc ) {
125128 int t = toI (v );
126129 if (t < minIndexFound ) {
@@ -144,12 +147,13 @@ private Pair<Graph<V>, Integer> findMinSCSG(int startIndex) {
144147 }
145148 }
146149
147- Pair <Graph <V >, Integer > result = Pair .of (dependencyGraph , minIndexFound );
150+ Object2IntMap .Entry <Graph <V >> result = new AbstractObject2IntMap .BasicEntry (dependencyGraph ,
151+ minIndexFound );
148152 clearMinSCCState ();
149153 return result ;
150154 }
151155
152- private List < Set <V >> findSCCS (int startIndex ) {
156+ private ObjectList < ObjectSet <V >> findSCCS (int startIndex ) {
153157 // Find SCCs in the subgraph induced
154158 // by vertices startIndex and beyond.
155159 // A call to StrongConnectivityAlgorithm
@@ -168,7 +172,7 @@ private List<Set<V>> findSCCS(int startIndex) {
168172 getSCCs (startIndex , vI );
169173 }
170174 }
171- List < Set <V >> result = foundSCCs ;
175+ ObjectList < ObjectSet <V >> result = foundSCCs ;
172176 foundSCCs = null ;
173177 return result ;
174178 }
@@ -195,7 +199,7 @@ private void getSCCs(int startIndex, int vertexIndex) {
195199 }
196200 }
197201 if (vLowlink .get (vertex ).equals (vIndex .get (vertex ))) {
198- Set <V > result = new HashSet <>();
202+ ObjectSet <V > result = new ObjectOpenHashSet <>();
199203 V temp ;
200204 do {
201205 temp = path .pop ();
@@ -225,7 +229,7 @@ private boolean findCyclesInSCG(int startIndex, int vertexIndex, Graph<V> scg) {
225229 for (V successor : scg .successors (vertex )) {
226230 int successorIndex = toI (successor );
227231 if (successorIndex == startIndex ) {
228- List <V > cycle = new ArrayList <>(stack .size ());
232+ ObjectList <V > cycle = new ObjectArrayList <>(stack .size ());
229233 stack .descendingIterator ().forEachRemaining (cycle ::add );
230234 cycleConsumer .accept (cycle );
231235 cycleVertexSuccessorConsumer .accept (vertex , successor ); // Paper
@@ -239,7 +243,7 @@ private boolean findCyclesInSCG(int startIndex, int vertexIndex, Graph<V> scg) {
239243 unblock (vertex );
240244 } else {
241245 for (V w : scg .successors (vertex )) {
242- Set <V > bSet = getBSet (w );
246+ ObjectSet <V > bSet = getBSet (w );
243247 bSet .add (vertex );
244248 }
245249 }
@@ -249,7 +253,7 @@ private boolean findCyclesInSCG(int startIndex, int vertexIndex, Graph<V> scg) {
249253
250254 private void unblock (V vertex ) {
251255 blocked .remove (vertex );
252- Set <V > bSet = getBSet (vertex );
256+ ObjectSet <V > bSet = getBSet (vertex );
253257 while (bSet .size () > 0 ) {
254258 V w = bSet .iterator ().next ();
255259 bSet .remove (w );
@@ -260,12 +264,12 @@ private void unblock(V vertex) {
260264 }
261265
262266 @ SuppressWarnings ("unchecked" )
263- private void initState (Consumer <List <V >> consumer ) {
267+ private void initState (Consumer <ObjectList <V >> consumer ) {
264268 cycleConsumer = consumer ;
265269 iToV = (V []) graph .nodes ().toArray ();
266- vToI = new HashMap <>();
267- blocked = new HashSet <>();
268- bSets = new HashMap <>();
270+ vToI = new Object2IntOpenHashMap <>();
271+ blocked = new ObjectOpenHashSet <>();
272+ bSets = new Object2ObjectOpenHashMap <>();
269273 stack = new ArrayDeque <>();
270274
271275 for (int i = 0 ; i < iToV .length ; i ++) {
@@ -284,11 +288,11 @@ private void clearState() {
284288
285289 private void initMinSCGState () {
286290 index = 0 ;
287- foundSCCs = new ArrayList <>();
288- vIndex = new HashMap <>();
289- vLowlink = new HashMap <>();
291+ foundSCCs = new ObjectArrayList <>();
292+ vIndex = new Object2IntOpenHashMap <>();
293+ vLowlink = new Object2IntOpenHashMap <>();
290294 path = new ArrayDeque <>();
291- pathSet = new HashSet <>();
295+ pathSet = new ObjectOpenHashSet <>();
292296 }
293297
294298 private void clearMinSCCState () {
@@ -300,17 +304,17 @@ private void clearMinSCCState() {
300304 pathSet = null ;
301305 }
302306
303- private Integer toI (V vertex ) {
304- return vToI .get (vertex );
307+ private int toI (V vertex ) {
308+ return vToI .getInt (vertex );
305309 }
306310
307- private V toV (Integer i ) {
311+ private V toV (int i ) {
308312 return iToV [i ];
309313 }
310314
311- private Set <V > getBSet (V v ) {
315+ private ObjectSet <V > getBSet (V v ) {
312316 // B sets typically not all needed,
313317 // so instantiate lazily.
314- return bSets .computeIfAbsent (v , k -> new HashSet <>());
318+ return bSets .computeIfAbsent (v , k -> new ObjectOpenHashSet <>());
315319 }
316320}
0 commit comments