-
Notifications
You must be signed in to change notification settings - Fork 153
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Port
TopologicalSort
to Java (#4110)
Part of #4030 Ports the `TopologicalSort` class to Java. Once again, this is a direct translation, replacing functional idioms with either direct iteration or equivalent `Stream` functions. The only semantic change is returning an `Optional` rather than reporting an error when there's a cycle.
- Loading branch information
1 parent
2dbd10c
commit 35e32e9
Showing
5 changed files
with
61 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// Copyright (c) Runtime Verification, Inc. All Rights Reserved. | ||
package org.kframework; | ||
|
||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
import org.apache.commons.lang3.tuple.Pair; | ||
|
||
public class TopologicalSort { | ||
/** Topologically sort based on the provided edges, unless a cycle is present. */ | ||
public static <T> Optional<Stream<T>> tsort(Iterable<Pair<T, T>> edges) { | ||
Map<T, Set<T>> toPred = new HashMap<>(); | ||
for (Pair<T, T> edge : edges) { | ||
if (!toPred.containsKey(edge.getLeft())) { | ||
toPred.put(edge.getLeft(), new HashSet<>()); | ||
} | ||
if (!toPred.containsKey(edge.getRight())) { | ||
toPred.put(edge.getRight(), new HashSet<>()); | ||
} | ||
toPred.get(edge.getRight()).add(edge.getLeft()); | ||
} | ||
return tsortInternal(toPred, Stream.empty()); | ||
} | ||
|
||
private static <T> Optional<Stream<T>> tsortInternal(Map<T, Set<T>> toPreds, Stream<T> done) { | ||
Map<Boolean, List<Map.Entry<T, Set<T>>>> partition = | ||
toPreds.entrySet().stream() | ||
.collect(Collectors.partitioningBy((e) -> e.getValue().isEmpty())); | ||
List<Map.Entry<T, Set<T>>> noPreds = partition.get(true); | ||
Map<T, Set<T>> hasPreds = | ||
partition.get(false).stream() | ||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); | ||
if (noPreds.isEmpty()) { | ||
if (hasPreds.isEmpty()) { | ||
return Optional.of(done); | ||
} | ||
return Optional.empty(); | ||
} | ||
Set<T> found = noPreds.stream().map(Map.Entry::getKey).collect(Collectors.toSet()); | ||
for (Map.Entry<T, Set<T>> entry : hasPreds.entrySet()) { | ||
entry.getValue().removeAll(found); | ||
} | ||
return tsortInternal(hasPreds, Stream.concat(done, found.stream())); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters