Signal/Collect

Allows you to process large graphs in seconds.

Project on GitHub Get Started

Fast and scalable

Algorithms are automatically executed in parallel.

Easy to use

Many algorithms can be expressed in just a few lines of code.

Configurable

The defaults get you started quickly, but everything can be customized.


How it works

In Signal/Collect algorithms are written from the perspective of vertices and edges. Once a graph has been specified the edges will signal and the vertices will collect. When an edge signals it computes a message based on the state of its source vertex. This message is then sent along the edge to the target vertex of the edge. When a vertex collects it uses the received messages to update its state. These operations happen in parallel all over the graph until all messages have been collected and all vertex states have converged.

Many algorithms have very simple and elegant implementations in Signal/Collect. Please take the time to explore some of the example algorithms below.


Example Algorithms

import com.signalcollect._

object PageRank extends App {
  val graph = GraphBuilder.build
  graph.addVertex(new PageRankVertex(1))
  graph.addVertex(new PageRankVertex(2))
  graph.addEdge(1, new PageRankEdge(2))
  graph.addEdge(2, new PageRankEdge(1))
  graph.execute
  graph.foreachVertex(println(_))
  graph.shutdown
}

class PageRankVertex(id: Int, baseRank: Double = 0.15)
    extends DataGraphVertex(id, baseRank) {
  type Signal = Double
  def dampingFactor = 1 - baseRank
  def collect = baseRank + dampingFactor * signals.sum
}

class PageRankEdge(targetId: Int)
    extends DefaultEdge(targetId) {
  type Source = PageRankVertex
  def signal = source.state * weight / source.sumOfOutWeights
}
import com.signalcollect._

object SSSP extends App {
  val graph = GraphBuilder.build
  graph.addVertex(new Location(1, Some(0)))
  graph.addVertex(new Location(2))
  graph.addVertex(new Location(3))
  graph.addEdge(1, new Path(2))
  graph.addEdge(2, new Path(3))
  graph.execute
  graph.foreachVertex(println(_))
  graph.shutdown
}

class Location(id: Int, initialState: Option[Int] = None)
	extends DataFlowVertex(id, initialState) {
  type Signal = Int
  def collect(signal: Int) = state match {
    case None                      => Some(signal)
    case Some(currentShortestPath) => Some(math.min(currentShortestPath, signal))
  }
}

class Path(t: Int) extends OptionalSignalEdge(t) {
  def signal = source.state match {
    case None                => None
    case Some(distance: Int) => Some(distance + weight.toInt)
  }
}