Graph Theory
Currently implemented for the Jung library.
Eventually Axle will provide its own basic Graph implementation, which will remove
Jung as a dependency of axle-core
.
Directed Graph
Example with String
is the vertex value and an Edge
type with two values (a String
and an Int
) to represent the edges
val (a, b, c, d) = ("a", "b", "c", "d")
class Edge(val s: String, val i: Int)
Invoke the DirectedGraph
typeclass with type parameters that denote
that we will use Jung's DirectedSparseGraph
as the graph type, with
String
and Edge
as vertex and edge values, respectively.
import edu.uci.ics.jung.graph.DirectedSparseGraph
import axle.algebra._
import axle.jung._
val jdg = DirectedGraph.k2[DirectedSparseGraph, String, Edge]
Use the jdg
witness's make
method to create the directed graph
val dg = jdg.make(List(a, b, c, d),
List(
(a, b, new Edge("hello", 1)),
(b, c, new Edge("world", 4)),
(c, d, new Edge("hi", 3)),
(d, a, new Edge("earth", 1)),
(a, c, new Edge("!", 7)),
(b, d, new Edge("hey", 2))))
import cats.implicits._
import axle.syntax.directedgraph.directedGraphOps
import axle.syntax.finite.finiteOps
dg.vertexProjection.size
// res1: Int = 4
dg.edgeProjection.size
// res2: Int = 6
dg.findVertex(_ === "a").map(v => dg.successors(v))
// res3: Option[Set[String]] = Some(value = Set("b", "c"))
dg.findVertex(_ === "c").map(v => dg.successors(v))
// res4: Option[Set[String]] = Some(value = Set("d"))
dg.findVertex(_ === "c").map(v => dg.predecessors(v))
// res5: Option[Set[String]] = Some(value = Set("a", "b"))
dg.findVertex(_ === "c").map(v => dg.neighbors(v))
// res6: Option[Set[String]] = Some(value = Set("a", "b", "d"))
Create a Visualization of the graph
import cats.Show
implicit val showEdge: Show[Edge] = new Show[Edge] {
def show(e: Edge): String = e.s + " " + e.i
}
import axle.visualize._
val dVis = DirectedGraphVisualization[DirectedSparseGraph[String, Edge], String, Edge](
dg,
width = 300,
height = 300,
border = 10,
radius = 10,
arrowLength = 10,
color = Color.green,
borderColor = Color.black,
fontSize = 12
)
Render as sn SVG file
import axle.web._
import cats.effect._
dVis.svg[IO]("docwork/images/SimpleDirectedGraph.svg").unsafeRunSync()
Undirected Graph
An undirected graph using the same dataa:
val (a, b, c, d) = ("a", "b", "c", "d")
class Edge(val s: String, val i: Int)
Invoke the UndirectedGraph
typeclass with type parameters that denote
that we will use Jung's UndirectedSparseGraph
as the graph type, with
String
and Edge
as vertex and edge values, respectively.
import edu.uci.ics.jung.graph.UndirectedSparseGraph
import axle.algebra._
import axle.jung._
val jug = UndirectedGraph.k2[UndirectedSparseGraph, String, Edge]
Use the jug
witness's make
method to create the undirected graph
val ug = jug.make(List(a, b, c, d),
List(
(a, b, new Edge("hello", 10)),
(b, c, new Edge("world", 1)),
(c, d, new Edge("hi", 3)),
(d, a, new Edge("earth", 7)),
(a, c, new Edge("!", 1)),
(b, d, new Edge("hey", 2))))
import cats.implicits._
import axle.syntax.undirectedgraph.undirectedGraphOps
import axle.syntax.finite.finiteOps
ug.vertexProjection.size
// res9: Int = 4
ug.edgeProjection.size
// res10: Int = 6
ug.findVertex(_ == "c").map(v => ug.neighbors(v))
// res11: Option[Iterable[String]] = Some(value = Iterable("a", "b", "d"))
ug.findVertex(_ == "a").map(v => ug.neighbors(v))
// res12: Option[Iterable[String]] = Some(value = Iterable("b", "c", "d"))
Create a Visualization of the graph
import cats.Show
implicit val showEdge: Show[Edge] = new Show[Edge] {
def show(e: Edge): String = e.s + " " + e.i
}
import axle.visualize._
val uVis = UndirectedGraphVisualization[UndirectedSparseGraph[String, Edge], String, Edge](
ug,
width = 300,
height = 300,
border = 10,
color = Color.yellow)
Render as an SVG file
import axle.web._
import cats.effect._
uVis.svg[IO]("docwork/images/SimpleUndirectedGraph.svg").unsafeRunSync()