aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/graph
diff options
context:
space:
mode:
authorchick2020-08-14 19:47:53 -0700
committerJack Koenig2020-08-14 19:47:53 -0700
commit6fc742bfaf5ee508a34189400a1a7dbffe3f1cac (patch)
tree2ed103ee80b0fba613c88a66af854ae9952610ce /src/main/scala/firrtl/graph
parentb516293f703c4de86397862fee1897aded2ae140 (diff)
All of src/ formatted with scalafmt
Diffstat (limited to 'src/main/scala/firrtl/graph')
-rw-r--r--src/main/scala/firrtl/graph/DiGraph.scala46
-rw-r--r--src/main/scala/firrtl/graph/EdgeData.scala5
-rw-r--r--src/main/scala/firrtl/graph/EulerTour.scala61
-rw-r--r--src/main/scala/firrtl/graph/RenderDiGraph.scala78
4 files changed, 105 insertions, 85 deletions
diff --git a/src/main/scala/firrtl/graph/DiGraph.scala b/src/main/scala/firrtl/graph/DiGraph.scala
index 32bcac5f..7720028c 100644
--- a/src/main/scala/firrtl/graph/DiGraph.scala
+++ b/src/main/scala/firrtl/graph/DiGraph.scala
@@ -2,7 +2,7 @@
package firrtl.graph
-import scala.collection.{Map, Set, mutable}
+import scala.collection.{mutable, Map, Set}
import scala.collection.mutable.{LinkedHashMap, LinkedHashSet}
/** An exception that is raised when an assumed DAG has a cycle */
@@ -13,6 +13,7 @@ class PathNotFoundException extends Exception("Unreachable node")
/** A companion to create DiGraphs from mutable data */
object DiGraph {
+
/** Create a DiGraph from a MutableDigraph, representing the same graph */
def apply[T](mdg: MutableDiGraph[T]): DiGraph[T] = mdg
@@ -33,7 +34,8 @@ object DiGraph {
}
/** Represents common behavior of all directed graphs */
-class DiGraph[T] (private[graph] val edges: LinkedHashMap[T, LinkedHashSet[T]]) {
+class DiGraph[T](private[graph] val edges: LinkedHashMap[T, LinkedHashSet[T]]) {
+
/** Check whether the graph contains vertex v */
def contains(v: T): Boolean = edges.contains(v)
@@ -74,8 +76,7 @@ class DiGraph[T] (private[graph] val edges: LinkedHashMap[T, LinkedHashSet[T]])
try {
foundPath = path(vertex, node, blacklist = Set.empty)
true
- }
- catch {
+ } catch {
case _: PathNotFoundException =>
foundPath = Seq.empty[T]
false
@@ -138,7 +139,7 @@ class DiGraph[T] (private[graph] val edges: LinkedHashMap[T, LinkedHashSet[T]])
* @return a Map[T,T] from each visited node to its predecessor in the
* traversal
*/
- def BFS(root: T): Map[T,T] = BFS(root, Set.empty[T])
+ def BFS(root: T): Map[T, T] = BFS(root, Set.empty[T])
/** Performs breadth-first search on the directed graph, with a blacklist of nodes
*
@@ -147,8 +148,8 @@ class DiGraph[T] (private[graph] val edges: LinkedHashMap[T, LinkedHashSet[T]])
* @return a Map[T,T] from each visited node to its predecessor in the
* traversal
*/
- def BFS(root: T, blacklist: Set[T]): Map[T,T] = {
- val prev = new mutable.LinkedHashMap[T,T]
+ def BFS(root: T, blacklist: Set[T]): Map[T, T] = {
+ val prev = new mutable.LinkedHashMap[T, T]
val queue = new mutable.Queue[T]
queue.enqueue(root)
while (queue.nonEmpty) {
@@ -181,7 +182,9 @@ class DiGraph[T] (private[graph] val edges: LinkedHashMap[T, LinkedHashSet[T]])
* @param blacklist list of nodes to stop searching, if encountered
* @return a Set[T] of nodes reachable from `root`
*/
- def reachableFrom(root: T, blacklist: Set[T]): LinkedHashSet[T] = new LinkedHashSet[T] ++ BFS(root, blacklist).map({ case (k, v) => k })
+ def reachableFrom(root: T, blacklist: Set[T]): LinkedHashSet[T] = new LinkedHashSet[T] ++ BFS(root, blacklist).map({
+ case (k, v) => k
+ })
/** Finds a path (if one exists) from one node to another
*
@@ -238,7 +241,7 @@ class DiGraph[T] (private[graph] val edges: LinkedHashMap[T, LinkedHashSet[T]])
val callStack = new mutable.Stack[StrongConnectFrame[T]]
for (node <- getVertices) {
- callStack.push(new StrongConnectFrame(node,getEdges(node).iterator))
+ callStack.push(new StrongConnectFrame(node, getEdges(node).iterator))
while (!callStack.isEmpty) {
val frame = callStack.top
val v = frame.v
@@ -257,7 +260,7 @@ class DiGraph[T] (private[graph] val edges: LinkedHashMap[T, LinkedHashSet[T]])
val w = frame.edgeIter.next
if (!indices.contains(w)) {
frame.childCall = Some(w)
- callStack.push(new StrongConnectFrame(w,getEdges(w).iterator))
+ callStack.push(new StrongConnectFrame(w, getEdges(w).iterator))
} else if (onstack.contains(w)) {
lowlinks(v) = lowlinks(v).min(indices(w))
}
@@ -269,8 +272,7 @@ class DiGraph[T] (private[graph] val edges: LinkedHashMap[T, LinkedHashSet[T]])
val w = stack.pop
onstack -= w
scc += w
- }
- while (scc.last != v);
+ } while (scc.last != v);
sccs.append(scc.toSeq)
}
callStack.pop
@@ -291,7 +293,7 @@ class DiGraph[T] (private[graph] val edges: LinkedHashMap[T, LinkedHashSet[T]])
* @param start the node to start at
* @return a Map[T,Seq[Seq[T]]] where the value associated with v is the Seq of all paths from start to v
*/
- def pathsInDAG(start: T): LinkedHashMap[T,Seq[Seq[T]]] = {
+ def pathsInDAG(start: T): LinkedHashMap[T, Seq[Seq[T]]] = {
// paths(v) holds the set of paths from start to v
val paths = new LinkedHashMap[T, mutable.Set[Seq[T]]]
val queue = new mutable.Queue[T]
@@ -299,7 +301,7 @@ class DiGraph[T] (private[graph] val edges: LinkedHashMap[T, LinkedHashSet[T]])
def addBinding(n: T, p: Seq[T]): Unit = {
paths.getOrElseUpdate(n, new LinkedHashSet[Seq[T]]) += p
}
- addBinding(start,Seq(start))
+ addBinding(start, Seq(start))
queue += start
queue ++= linearize.filter(reachable.contains(_))
while (!queue.isEmpty) {
@@ -310,22 +312,25 @@ class DiGraph[T] (private[graph] val edges: LinkedHashMap[T, LinkedHashSet[T]])
}
}
}
- paths.map({ case (k,v) => (k,v.toSeq) })
+ paths.map({ case (k, v) => (k, v.toSeq) })
}
/** Returns a graph with all edges reversed */
def reverse: DiGraph[T] = {
val mdg = new MutableDiGraph[T]
edges.foreach({ case (u, edges) => mdg.addVertex(u) })
- edges.foreach({ case (u, edges) =>
- edges.foreach(v => mdg.addEdge(v,u))
+ edges.foreach({
+ case (u, edges) =>
+ edges.foreach(v => mdg.addEdge(v, u))
})
DiGraph(mdg)
}
private def filterEdges(vprime: Set[T]): LinkedHashMap[T, LinkedHashSet[T]] = {
- def filterNodeSet(s: LinkedHashSet[T]): LinkedHashSet[T] = s.filter({ case (k) => vprime.contains(k) })
- def filterAdjacencyLists(m: LinkedHashMap[T, LinkedHashSet[T]]): LinkedHashMap[T, LinkedHashSet[T]] = m.map({ case (k, v) => (k, filterNodeSet(v)) })
+ def filterNodeSet(s: LinkedHashSet[T]): LinkedHashSet[T] = s.filter({ case (k) => vprime.contains(k) })
+ def filterAdjacencyLists(m: LinkedHashMap[T, LinkedHashSet[T]]): LinkedHashMap[T, LinkedHashSet[T]] = m.map({
+ case (k, v) => (k, filterNodeSet(v))
+ })
val eprime: LinkedHashMap[T, LinkedHashSet[T]] = edges.filter({ case (k, v) => vprime.contains(k) })
filterAdjacencyLists(eprime)
}
@@ -354,7 +359,7 @@ class DiGraph[T] (private[graph] val edges: LinkedHashMap[T, LinkedHashSet[T]])
*/
def simplify(vprime: Set[T]): DiGraph[T] = {
require(vprime.subsetOf(edges.keySet))
- val pathEdges = vprime.map(v => (v, reachableFrom(v) & (vprime-v)) )
+ val pathEdges = vprime.map(v => (v, reachableFrom(v) & (vprime - v)))
new DiGraph(new LinkedHashMap[T, LinkedHashSet[T]] ++ pathEdges)
}
@@ -384,6 +389,7 @@ class DiGraph[T] (private[graph] val edges: LinkedHashMap[T, LinkedHashSet[T]])
}
class MutableDiGraph[T] extends DiGraph[T](new LinkedHashMap[T, LinkedHashSet[T]]) {
+
/** Add vertex v to the graph
* @return v, the added vertex
*/
diff --git a/src/main/scala/firrtl/graph/EdgeData.scala b/src/main/scala/firrtl/graph/EdgeData.scala
index 16990de0..6a63c3b9 100644
--- a/src/main/scala/firrtl/graph/EdgeData.scala
+++ b/src/main/scala/firrtl/graph/EdgeData.scala
@@ -6,11 +6,10 @@ import scala.collection.mutable
/**
* An exception that indicates that an edge cannot be found in a graph with edge data.
- *
+ *
* @note the vertex type is not captured as a type parameter, as it would be erased.
*/
-class EdgeNotFoundException(u: Any, v: Any)
- extends IllegalArgumentException(s"Edge (${u}, ${v}) does not exist!")
+class EdgeNotFoundException(u: Any, v: Any) extends IllegalArgumentException(s"Edge (${u}, ${v}) does not exist!")
/**
* Mixing this trait into a DiGraph indicates that each edge may be associated with an optional
diff --git a/src/main/scala/firrtl/graph/EulerTour.scala b/src/main/scala/firrtl/graph/EulerTour.scala
index 2d8a17e2..5e075ae2 100644
--- a/src/main/scala/firrtl/graph/EulerTour.scala
+++ b/src/main/scala/firrtl/graph/EulerTour.scala
@@ -6,6 +6,7 @@ import scala.collection.mutable
/** Euler Tour companion object */
object EulerTour {
+
/** Create an Euler Tour of a `DiGraph[T]` */
def apply[T](diGraph: DiGraph[T], start: T): EulerTour[Seq[T]] = {
val r = mutable.Map[Seq[T], Int]()
@@ -66,8 +67,8 @@ class EulerTour[T](r: Map[T, Int], e: Seq[T], h: Seq[Int]) {
* the index of that minimum in each block, b.
*/
private lazy val blocks = (h ++ (1 to (m - n % m))).grouped(m).toArray
- private lazy val a = blocks map (_.min)
- private lazy val b = blocks map (b => b.indexOf(b.min))
+ private lazy val a = blocks.map(_.min)
+ private lazy val b = blocks.map(b => b.indexOf(b.min))
/** Construct a Sparse Table (ST) representation for the minimum index
* of a sequence of integers. Data in the returned array is indexed
@@ -75,7 +76,10 @@ class EulerTour[T](r: Map[T, Int], e: Seq[T], h: Seq[Int]) {
*/
private def constructSparseTable(x: Seq[Int]): Array[Array[Int]] = {
val tmp = Array.ofDim[Int](x.size + 1, math.ceil(lg(x.size)).toInt)
- for (i <- 0 to x.size - 1; j <- 0 to math.ceil(lg(x.size)).toInt - 1) {
+ for {
+ i <- 0 to x.size - 1
+ j <- 0 to math.ceil(lg(x.size)).toInt - 1
+ } {
tmp(i)(j) = -1
}
@@ -86,11 +90,11 @@ class EulerTour[T](r: Map[T, Int], e: Seq[T], h: Seq[Int]) {
} else {
val (a, b, c) = (base, base + (1 << (size - 1)), size - 1)
- val l = if (tmp(a)(c) != -1) { tmp(a)(c) }
- else { tableRecursive(a, c) }
+ val l = if (tmp(a)(c) != -1) { tmp(a)(c) }
+ else { tableRecursive(a, c) }
- val r = if (tmp(b)(c) != -1) { tmp(b)(c) }
- else { tableRecursive(b, c) }
+ val r = if (tmp(b)(c) != -1) { tmp(b)(c) }
+ else { tableRecursive(b, c) }
val min = if (x(l) < x(r)) l else r
tmp(base)(size) = min
@@ -99,9 +103,11 @@ class EulerTour[T](r: Map[T, Int], e: Seq[T], h: Seq[Int]) {
}
}
- for (i <- (0 to x.size - 1);
- j <- (0 to math.ceil(lg(x.size)).toInt - 1);
- if i + (1 << j) - 1 < x.size) {
+ for {
+ i <- (0 to x.size - 1)
+ j <- (0 to math.ceil(lg(x.size)).toInt - 1)
+ if i + (1 << j) - 1 < x.size
+ } {
tableRecursive(i, j)
}
tmp
@@ -117,16 +123,26 @@ class EulerTour[T](r: Map[T, Int], e: Seq[T], h: Seq[Int]) {
}
val size = m - 1
- val out = Seq.fill(size)(Seq(-1, 1))
- .flatten.combinations(m - 1).flatMap(_.permutations).toList
+ val out = Seq
+ .fill(size)(Seq(-1, 1))
+ .flatten
+ .combinations(m - 1)
+ .flatMap(_.permutations)
+ .toList
.sortWith(sortSeqSeq)
.map(_.foldLeft(Seq(0))((h, pm) => (h.head + pm) +: h).reverse)
- .map{ a =>
+ .map { a =>
val tmp = Array.ofDim[Int](m, m)
- for (i <- 0 to size; j <- i to size) yield {
+ for {
+ i <- 0 to size
+ j <- i to size
+ } yield {
val window = a.slice(i, j + 1)
- tmp(i)(j) = window.indexOf(window.min) + i }
- tmp }.toArray
+ tmp(i)(j) = window.indexOf(window.min) + i
+ }
+ tmp
+ }
+ .toArray
out
}
private lazy val tables = constructTableLookups(m)
@@ -167,7 +183,7 @@ class EulerTour[T](r: Map[T, Int], e: Seq[T], h: Seq[Int]) {
// Compute block and word indices
val (block_i, block_j) = (i / m, j / m)
- val (word_i, word_j) = (i % m, j % m)
+ val (word_i, word_j) = (i % m, j % m)
/** Up to four possible minimum indices are then computed based on the
* following conditions:
@@ -187,12 +203,12 @@ class EulerTour[T](r: Map[T, Int], e: Seq[T], h: Seq[Int]) {
val min_i = block_i * m + tables(tableIdx(block_i))(word_i)(word_j)
Seq(min_i)
case (bi, bj) if (block_i == block_j - 1) =>
- val min_i = block_i * m + tables(tableIdx(block_i))(word_i)( m - 1)
- val min_j = block_j * m + tables(tableIdx(block_j))( 0)(word_j)
+ val min_i = block_i * m + tables(tableIdx(block_i))(word_i)(m - 1)
+ val min_j = block_j * m + tables(tableIdx(block_j))(0)(word_j)
Seq(min_i, min_j)
case _ =>
- val min_i = block_i * m + tables(tableIdx(block_i))(word_i)( m - 1)
- val min_j = block_j * m + tables(tableIdx(block_j))( 0)(word_j)
+ val min_i = block_i * m + tables(tableIdx(block_i))(word_i)(m - 1)
+ val min_j = block_j * m + tables(tableIdx(block_j))(0)(word_j)
val (min_between_l, min_between_r) = {
val range = math.floor(lg(block_j - block_i - 1)).toInt
val base_0 = block_i + 1
@@ -200,7 +216,8 @@ class EulerTour[T](r: Map[T, Int], e: Seq[T], h: Seq[Int]) {
val (idx_0, idx_1) = (st(base_0)(range), st(base_1)(range))
val (min_0, min_1) = (b(idx_0) + idx_0 * m, b(idx_1) + idx_1 * m)
- (min_0, min_1) }
+ (min_0, min_1)
+ }
Seq(min_i, min_between_l, min_between_r, min_j)
}
diff --git a/src/main/scala/firrtl/graph/RenderDiGraph.scala b/src/main/scala/firrtl/graph/RenderDiGraph.scala
index b3c1373c..45be3a8f 100644
--- a/src/main/scala/firrtl/graph/RenderDiGraph.scala
+++ b/src/main/scala/firrtl/graph/RenderDiGraph.scala
@@ -16,7 +16,6 @@ import scala.collection.mutable
*/
class RenderDiGraph[T <: Any](diGraph: DiGraph[T], graphName: String = "", rankDir: String = "LR") {
-
/**
* override this to change the default way a node is displayed. Default is toString surrounded by double quotes
* This example changes the double quotes to brackets
@@ -38,8 +37,7 @@ class RenderDiGraph[T <: Any](diGraph: DiGraph[T], graphName: String = "", rankD
try {
diGraph.linearize
- }
- catch {
+ } catch {
case cyclicException: CyclicException =>
val node = cyclicException.node.asInstanceOf[T]
path = diGraph.findLoopAtNode(node)
@@ -61,31 +59,29 @@ class RenderDiGraph[T <: Any](diGraph: DiGraph[T], graphName: String = "", rankD
val loop = findOneLoop
- if(loop.nonEmpty) {
+ if (loop.nonEmpty) {
// Find all the children of the nodes in the loop
val childrenFound = diGraph.getEdgeMap.flatMap {
case (node, children) if loop.contains(node) => children
- case _ => Seq.empty
+ case _ => Seq.empty
}.toSet
// Create a new DiGraph containing only loop and direct children or parents
val edgeData = diGraph.getEdgeMap
- val newEdgeData = edgeData.flatMap { case (node, children) =>
- if(loop.contains(node)) {
- Some(node -> children)
- }
- else if(childrenFound.contains(node)) {
- Some(node -> children.intersect(loop))
- }
- else {
- val newChildren = children.intersect(loop)
- if(newChildren.nonEmpty) {
- Some(node -> newChildren)
- }
- else {
- None
- }
+ val newEdgeData = edgeData.flatMap {
+ case (node, children) =>
+ if (loop.contains(node)) {
+ Some(node -> children)
+ } else if (childrenFound.contains(node)) {
+ Some(node -> children.intersect(loop))
+ } else {
+ val newChildren = children.intersect(loop)
+ if (newChildren.nonEmpty) {
+ Some(node -> newChildren)
+ } else {
+ None
+ }
}
}
@@ -96,8 +92,7 @@ class RenderDiGraph[T <: Any](diGraph: DiGraph[T], graphName: String = "", rankD
}
}
newRenderer.toDotWithLoops(loop, getRankedNodes)
- }
- else {
+ } else {
""
}
}
@@ -114,10 +109,11 @@ class RenderDiGraph[T <: Any](diGraph: DiGraph[T], graphName: String = "", rankD
val edges = diGraph.getEdgeMap
- edges.foreach { case (parent, children) =>
- children.foreach { child =>
- s.append(s""" ${renderNode(parent)} -> ${renderNode(child)};""" + "\n")
- }
+ edges.foreach {
+ case (parent, children) =>
+ children.foreach { child =>
+ s.append(s""" ${renderNode(parent)} -> ${renderNode(child)};""" + "\n")
+ }
}
s.append("}\n")
s.toString
@@ -137,24 +133,25 @@ class RenderDiGraph[T <: Any](diGraph: DiGraph[T], graphName: String = "", rankD
val edges = diGraph.getEdgeMap
- edges.foreach { case (parent, children) =>
- allNodes += parent
- allNodes ++= children
+ edges.foreach {
+ case (parent, children) =>
+ allNodes += parent
+ allNodes ++= children
- children.foreach { child =>
- val highlight = if(loopedNodes.contains(parent) && loopedNodes.contains(child)) {
- "[color=red,penwidth=3.0]"
- }
- else {
- ""
+ children.foreach { child =>
+ val highlight = if (loopedNodes.contains(parent) && loopedNodes.contains(child)) {
+ "[color=red,penwidth=3.0]"
+ } else {
+ ""
+ }
+ s.append(s""" ${renderNode(parent)} -> ${renderNode(child)}$highlight;""" + "\n")
}
- s.append(s""" ${renderNode(parent)} -> ${renderNode(child)}$highlight;""" + "\n")
- }
}
val paredRankedNodes = rankedNodes.flatMap { nodes =>
val newNodes = nodes.filter(allNodes.contains)
- if(newNodes.nonEmpty) { Some(newNodes) } else { None }
+ if (newNodes.nonEmpty) { Some(newNodes) }
+ else { None }
}
paredRankedNodes.foreach { nodesAtRank =>
@@ -183,7 +180,7 @@ class RenderDiGraph[T <: Any](diGraph: DiGraph[T], graphName: String = "", rankD
diGraph.getEdges(node)
}.filterNot(alreadyVisited.contains).distinct
- if(nextNodes.nonEmpty) {
+ if (nextNodes.nonEmpty) {
walkByRank(nextNodes, rankNumber + 1)
}
}
@@ -191,6 +188,7 @@ class RenderDiGraph[T <: Any](diGraph: DiGraph[T], graphName: String = "", rankD
walkByRank(diGraph.findSources.toSeq)
rankNodes
}
+
/**
* Convert this graph into input for the graphviz dot program.
* It tries to align nodes in columns based
@@ -216,7 +214,7 @@ class RenderDiGraph[T <: Any](diGraph: DiGraph[T], graphName: String = "", rankD
children
}.filterNot(alreadyVisited.contains).distinct
- if(nextNodes.nonEmpty) {
+ if (nextNodes.nonEmpty) {
walkByRank(nextNodes, rankNumber + 1)
}
}