Algorithms are automatically executed in parallel.
Many algorithms can be expressed in just a few lines of code.
The defaults get you started quickly, but everything can be customized.
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.
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)
}
}