This is a simple multiplatform graph library. Among the platforms currently supported are
JVM
, JavaScript
and Linux AMD64
. If you suppose to use other platforms feel free to
add it in this library through fork and pull request.
For the linux installation the libtinfo5
library is required. In Ubuntu you can install it as:
sudo apt-get install libtinfo5
On any Linux system you can invoke:
gradlew build
On any Windows system you can invoke:
gradlew.bat build
For the detailed examples of this library usage please see the tests. Here some of the cases are briefly listed.
val v1 = SimpleVertex("v1")
val v2 = SimpleVertex("v2")
val v3 = SimpleVertex("v3")
val v4 = SimpleVertex("v4")
val v5 = SimpleVertex("v5")
val v6 = SimpleVertex("v6")
val v7 = SimpleVertex("v7")
val e1 = SimpleDirectedEdge(v1, v2)
val e2 = SimpleDirectedEdge(v1, v3)
val e3 = SimpleDirectedEdge(v2, v4)
val e4 = SimpleDirectedEdge(v3, v5)
val e5 = SimpleDirectedEdge(v4, v6)
val e6 = SimpleDirectedEdge(v5, v7)
val e7 = SimpleDirectedEdge(v6, v7)
SimpleDirectedGraph() init {
// Vertices
+v1
+v2
+v3
+v4
+v5
+v6
+v7
// Edges
+e1
+e2
+e3
+e4
+e5
+e6
+e7
}
val path = graph.path(v1, v7) { edge ->
1.0
}
var v1 = new SimpleVertex("v1");
var v2 = new SimpleVertex("v2");
var v3 = new SimpleVertex("v3");
var v4 = new SimpleVertex("v4");
var e1 = new SimpleDirectedEdge<>(v1, v2);
var e2 = new SimpleDirectedEdge<>(v2, v3);
var e3 = new SimpleDirectedEdge<>(v1, v3);
var e4 = new SimpleDirectedEdge<>(v1, v4);
var e5 = new SimpleDirectedEdge<>(v2, v4);
var e6 = new SimpleDirectedEdge<>(v3, v4);
var graph = new GraphInMemory<>();
graph.setVertices(Arrays.asList(v1, v2, v3, v4));
graph.setEdges(Arrays.asList(e1, e2, e3, e4, e5, e6));
var edges = StreamSupport.stream(graph.getEdges().spliterator(), false).collect(Collectors.toList());
var vertices = StreamSupport.stream(graph.getVertices().spliterator(), false).collect(Collectors.toList());
var path = graph.path(v1, v4);
var pathWeighted = graph.path(v1, v4, toKotlin(e -> 1.0));
TODO
TODO
In order to implement custom logics you can create your own classes for vertices and edges. They must implement respectively IVertex and ITypedEdge interfaces. To declare a class for vertices you do:
class MyVertex(): IVertex
Here you need to pay a special attention to the hashCode
and equal
methods since this class is used as a key
for HashMaps.
Thus, edges may be declared like that:
data class WeightedEdge(
override val from: MyVertex,
override val to: MyVertex,
override val weight: Double
): ITypedEdge<MyVertex>
Then you need to declare a typealias for graph class:
typealias MyGraph = GraphInMemory<MyVertex, WeightedEdge>
Otherway you need to create your own realization for the graph. So, I recommend to inherit it from AbstractGraph
.
Now you can fill your graph with data:
val myGraph = MyGraph() init {
val v1 = MyVertex()
val v2 = MyVertex()
+v1
+v2
+WeightedEdge(v1, v2, 3.0)
}
... and compute the optimal path between vertices:
val path = graph.path(v1, v2) { edge ->
// In this lambda you provide the weights to the path method
edge.weight
}
The default graph realization of GraphInMemory
is not thread safe by default. It does not matter for JavaScript,
as it doesn't operate with threads, but that must be specially attentiond for JVM and Linux platforms.
For the JVM platform there is a decorator class implemented ConcurrentGraph
. By default it just decorates the
GraphInMemory
class. If you want to make your own realization concurrent you need to use it as follows:
val myConcurrentGraph = ConcurrentGraph(
vertices = myVertices,
edges = myEdges,
instance = MyCustomGraph()
)
There may be different algorythms used for optimal path search. Right now there is only one implemented: Dijkstra's algorithm. If your graph allows A* search algorithm you better use that instead. To do that you need your class to implement ISearchPath interface and create a creator class implementing IBuildAlgorithm interface. Then you need to inject your searcher instance to the graph class:
class AStarPath(val graph: IGraph): ISearchPath { /* ... */ }
class AStarPathCreator(): IBuildAlorithm<ISearchPath> {
private var graph: IGraph = IGraph.EMPTY
fun graph(graph: IGraph) { this.graph = graph }
fun create() = AStarPath(graph)
}
val graph = MyGraph(
vertices = myVertices,
edges = myEdges,
pathSearcherCreator = AStarPathCreator()
)
- A decorator class is required specially for Java since Java does not support Kotlin non-nullables and some other features.