From 872867559faa23e54047dc5242d2415bde58fbe1 Mon Sep 17 00:00:00 2001 From: norangebit Date: Sun, 19 May 2019 19:40:00 +0200 Subject: [PATCH] add weight graph --- .../algorithms/graph/GraphInterface.kt | 13 ++ .../algorithms/graph/WeightDiGraph.kt | 55 +++++++++ .../norangeb/algorithms/graph/WeightGraph.kt | 45 +++++++ .../it/norangeb/algorithms/graph/data/Edge.kt | 42 +++++++ .../norangeb/algorithms/graph/data/EdgeI.kt | 33 ++++++ .../algorithms/graph/data/GraphData.kt | 7 ++ .../graph/data/WeightAdjacentList.kt | 59 +++++++++ .../graph/data/WeightAdjacentMatrix.kt | 55 +++++++++ .../graph/operations/DepthFirstOrder.kt | 1 - .../norangeb/algorithms/graph/DiGraphTest.kt | 2 +- .../algorithms/graph/WeightDiGraphTest.kt | 112 ++++++++++++++++++ .../algorithms/graph/WeightGraphTest.kt | 81 +++++++++++++ .../graph/data/WeightAdjacentListTest.kt | 91 ++++++++++++++ .../graph/data/WeightAdjacentMatrixTest.kt | 91 ++++++++++++++ 14 files changed, 685 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/it/norangeb/algorithms/graph/WeightDiGraph.kt create mode 100644 src/main/kotlin/it/norangeb/algorithms/graph/WeightGraph.kt create mode 100644 src/main/kotlin/it/norangeb/algorithms/graph/data/Edge.kt create mode 100644 src/main/kotlin/it/norangeb/algorithms/graph/data/EdgeI.kt create mode 100644 src/main/kotlin/it/norangeb/algorithms/graph/data/WeightAdjacentList.kt create mode 100644 src/main/kotlin/it/norangeb/algorithms/graph/data/WeightAdjacentMatrix.kt create mode 100644 src/test/kotlin/it/norangeb/algorithms/graph/WeightDiGraphTest.kt create mode 100644 src/test/kotlin/it/norangeb/algorithms/graph/WeightGraphTest.kt create mode 100644 src/test/kotlin/it/norangeb/algorithms/graph/data/WeightAdjacentListTest.kt create mode 100644 src/test/kotlin/it/norangeb/algorithms/graph/data/WeightAdjacentMatrixTest.kt diff --git a/src/main/kotlin/it/norangeb/algorithms/graph/GraphInterface.kt b/src/main/kotlin/it/norangeb/algorithms/graph/GraphInterface.kt index 441f738..653ea19 100644 --- a/src/main/kotlin/it/norangeb/algorithms/graph/GraphInterface.kt +++ b/src/main/kotlin/it/norangeb/algorithms/graph/GraphInterface.kt @@ -25,6 +25,8 @@ package it.norangeb.algorithms.graph +import it.norangeb.algorithms.graph.data.EdgeI + interface UndirectedGraph { fun vertexNumber(): Int fun edgeNumber(): Int @@ -34,4 +36,15 @@ interface UndirectedGraph { interface DirectedGraph : UndirectedGraph { fun reverse(): DirectedGraph +} + +interface WeightUndirectedGraph { + fun vertexNumber(): Int + fun edgeNumber(): Int + fun addEdge(edge: EdgeI) + fun adjacentVertex(vertex: Int): Collection +} + +interface WeightDirectedGraph : WeightUndirectedGraph { + fun reverse(): WeightDirectedGraph } \ No newline at end of file diff --git a/src/main/kotlin/it/norangeb/algorithms/graph/WeightDiGraph.kt b/src/main/kotlin/it/norangeb/algorithms/graph/WeightDiGraph.kt new file mode 100644 index 0000000..b6b4766 --- /dev/null +++ b/src/main/kotlin/it/norangeb/algorithms/graph/WeightDiGraph.kt @@ -0,0 +1,55 @@ +/* + * MIT License + * + * Copyright (c) 2019 norangebit + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package it.norangeb.algorithms.graph + +import it.norangeb.algorithms.graph.data.EdgeI +import it.norangeb.algorithms.graph.data.WeightAdjacentList +import it.norangeb.algorithms.graph.data.WeightGraphData + +class WeightDiGraph( + private val data: WeightGraphData = WeightAdjacentList() +) : WeightDirectedGraph { + override fun vertexNumber(): Int = data.vertexNumber() + + override fun edgeNumber(): Int = data.edgeNumber() + + override fun addEdge(edge: EdgeI) = data.addEdge(edge) + + override fun adjacentVertex(vertex: Int): Collection = data.adjacent(vertex) + + override fun reverse(): WeightDirectedGraph { + val reverse = WeightDiGraph() + + (0 until data.vertexNumber()) + .forEach { from -> + data.adjacent(from).forEach { + reverse.addEdge(it.reversed()) + } + } + + return reverse + } +} \ No newline at end of file diff --git a/src/main/kotlin/it/norangeb/algorithms/graph/WeightGraph.kt b/src/main/kotlin/it/norangeb/algorithms/graph/WeightGraph.kt new file mode 100644 index 0000000..d40eaad --- /dev/null +++ b/src/main/kotlin/it/norangeb/algorithms/graph/WeightGraph.kt @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (c) 2019 norangebit + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package it.norangeb.algorithms.graph + +import it.norangeb.algorithms.graph.data.EdgeI +import it.norangeb.algorithms.graph.data.WeightAdjacentList +import it.norangeb.algorithms.graph.data.WeightGraphData + +class WeightGraph( + private val data: WeightGraphData = WeightAdjacentList() +) : WeightUndirectedGraph { + override fun vertexNumber(): Int = data.vertexNumber() + + override fun edgeNumber(): Int = data.edgeNumber() / 2 + + override fun addEdge(edge: EdgeI) { + data.addEdge(edge) + data.addEdge(edge.reversed()) + } + + override fun adjacentVertex(vertex: Int): Collection = data.adjacent(vertex) +} \ No newline at end of file diff --git a/src/main/kotlin/it/norangeb/algorithms/graph/data/Edge.kt b/src/main/kotlin/it/norangeb/algorithms/graph/data/Edge.kt new file mode 100644 index 0000000..1bf84cd --- /dev/null +++ b/src/main/kotlin/it/norangeb/algorithms/graph/data/Edge.kt @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (c) 2019 norangebit + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package it.norangeb.algorithms.graph.data + +data class Edge(val from: Int, val to: Int, val weight: Double) : EdgeI { + override fun weight(): Double = weight + + override fun either(): Int = from + + override fun other(vertex: Int): Int = when (vertex) { + from -> to + else -> from + } + + override fun compareTo(other: EdgeI): Int = + this.weight.compareTo(other.weight()) + + override fun reversed(): EdgeI = Edge(to, from, weight) +} \ No newline at end of file diff --git a/src/main/kotlin/it/norangeb/algorithms/graph/data/EdgeI.kt b/src/main/kotlin/it/norangeb/algorithms/graph/data/EdgeI.kt new file mode 100644 index 0000000..5593ab2 --- /dev/null +++ b/src/main/kotlin/it/norangeb/algorithms/graph/data/EdgeI.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright (c) 2019 norangebit + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package it.norangeb.algorithms.graph.data + +interface EdgeI : Comparable { + fun weight(): Double + fun either(): Int + fun other(vertex: Int): Int + fun reversed(): EdgeI +} \ No newline at end of file diff --git a/src/main/kotlin/it/norangeb/algorithms/graph/data/GraphData.kt b/src/main/kotlin/it/norangeb/algorithms/graph/data/GraphData.kt index 49e3b75..1e6855c 100644 --- a/src/main/kotlin/it/norangeb/algorithms/graph/data/GraphData.kt +++ b/src/main/kotlin/it/norangeb/algorithms/graph/data/GraphData.kt @@ -30,4 +30,11 @@ interface GraphData { fun adjacent(vertex: Int): Collection fun vertexNumber(): Int fun edgeNumber(): Int +} + +interface WeightGraphData { + fun addEdge(edgeI: EdgeI) + fun adjacent(vertex: Int): Collection + fun vertexNumber(): Int + fun edgeNumber(): Int } \ No newline at end of file diff --git a/src/main/kotlin/it/norangeb/algorithms/graph/data/WeightAdjacentList.kt b/src/main/kotlin/it/norangeb/algorithms/graph/data/WeightAdjacentList.kt new file mode 100644 index 0000000..1902c65 --- /dev/null +++ b/src/main/kotlin/it/norangeb/algorithms/graph/data/WeightAdjacentList.kt @@ -0,0 +1,59 @@ +/* + * MIT License + * + * Copyright (c) 2019 norangebit + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package it.norangeb.algorithms.graph.data + +import java.util.TreeMap +import kotlin.math.max + +class WeightAdjacentList : WeightGraphData { + private val graph = TreeMap>() + private var edgeNumber = 0 + private var maxVertexId = 0 + + override fun addEdge(edgeI: EdgeI) { + val from = edgeI.either() + + graph.computeIfAbsent(from) { mutableListOf() } + + graph[from]?.add(edgeI) + + computeMaxVertexId(from, edgeI.other(from)) + edgeNumber++ + } + + override fun adjacent(vertex: Int): Collection { + return graph[vertex] ?: listOf() + } + + override fun vertexNumber(): Int = maxVertexId + 1 + + override fun edgeNumber(): Int = edgeNumber + + private fun computeMaxVertexId(firstVertex: Int, secondVertex: Int) { + val max = max(firstVertex, secondVertex) + maxVertexId = max(max, maxVertexId) + } +} \ No newline at end of file diff --git a/src/main/kotlin/it/norangeb/algorithms/graph/data/WeightAdjacentMatrix.kt b/src/main/kotlin/it/norangeb/algorithms/graph/data/WeightAdjacentMatrix.kt new file mode 100644 index 0000000..b182a7c --- /dev/null +++ b/src/main/kotlin/it/norangeb/algorithms/graph/data/WeightAdjacentMatrix.kt @@ -0,0 +1,55 @@ +/* + * MIT License + * + * Copyright (c) 2019 norangebit + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package it.norangeb.algorithms.graph.data + +class WeightAdjacentMatrix(private val vertexNumber: Int) : WeightGraphData { + private val graph = Array(vertexNumber) { + Array(vertexNumber) { null } + } + + override fun addEdge(edgeI: EdgeI) { + val from = edgeI.either() + + graph[from][edgeI.other(from)] = edgeI.weight() + } + + override fun adjacent(vertex: Int): Collection { + return graph[vertex] + .mapIndexed { index, d -> + if (d != null) Edge(vertex, index, d) + else null + } + .mapNotNull { it } + } + + override fun vertexNumber(): Int = vertexNumber + + override fun edgeNumber(): Int { + return graph + .map { it.count { it != null } } + .sum() + } +} \ No newline at end of file diff --git a/src/main/kotlin/it/norangeb/algorithms/graph/operations/DepthFirstOrder.kt b/src/main/kotlin/it/norangeb/algorithms/graph/operations/DepthFirstOrder.kt index 788501a..5f88921 100644 --- a/src/main/kotlin/it/norangeb/algorithms/graph/operations/DepthFirstOrder.kt +++ b/src/main/kotlin/it/norangeb/algorithms/graph/operations/DepthFirstOrder.kt @@ -67,5 +67,4 @@ class DepthFirstOrder(graph: UndirectedGraph) { fun reversePostOrder(): Iterable { return postOrder.reversed() } - } \ No newline at end of file diff --git a/src/test/kotlin/it/norangeb/algorithms/graph/DiGraphTest.kt b/src/test/kotlin/it/norangeb/algorithms/graph/DiGraphTest.kt index 4e3138e..9b216ac 100644 --- a/src/test/kotlin/it/norangeb/algorithms/graph/DiGraphTest.kt +++ b/src/test/kotlin/it/norangeb/algorithms/graph/DiGraphTest.kt @@ -87,7 +87,7 @@ object DiGraphTest : Spek({ result = diGraph.reverse() } - Then("adjacent of 0 should euqals listOf(1)") { + Then("adjacent of 0 should equals listOf(1)") { result.adjacentVertex(0) `should equal` listOf(1) } diff --git a/src/test/kotlin/it/norangeb/algorithms/graph/WeightDiGraphTest.kt b/src/test/kotlin/it/norangeb/algorithms/graph/WeightDiGraphTest.kt new file mode 100644 index 0000000..f72a97a --- /dev/null +++ b/src/test/kotlin/it/norangeb/algorithms/graph/WeightDiGraphTest.kt @@ -0,0 +1,112 @@ +/* + * MIT License + * + * Copyright (c) 2019 norangebit + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package it.norangeb.algorithms.graph + +import it.norangeb.algorithms.graph.data.Edge +import org.amshove.kluent.`should be equal to` +import org.amshove.kluent.`should equal` +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.gherkin.Feature + +object WeightDiGraphTest : Spek({ + Feature("weight directed graph") { + val graph by memoized { WeightDiGraph() } + + Scenario("add edges") { + When("add edge 1->4:1.4") { + graph.addEdge(Edge(1, 4, 1.4)) + } + + Then("number of edge should equal to 1") { + graph.edgeNumber() `should be equal to` 1 + } + + Then("adjacent of 1 should equal listOf(1->4:1.4)") { + graph.adjacentVertex(1) `should equal` listOf(Edge(1, 4, 1.4)) + } + + Then("adjacent of 4 should be empty") { + graph.adjacentVertex(4).isEmpty() `should be equal to` true + } + + When("add edge 1->3:1.3, 3->4:3.4, 1->5:1.5") { + graph.addEdge(Edge(1, 3, 1.3)) + graph.addEdge(Edge(3, 4, 3.4)) + graph.addEdge(Edge(1, 5, 1.5)) + } + + Then("number of edge should equal to 4") { + graph.edgeNumber() `should be equal to` 4 + } + + Then("adjacent of 1 should equal listOf(1->3:1.3, 1->4:1.4, 1->5:1.5)") { + graph.adjacentVertex(1).sorted() `should equal` listOf( + Edge(1, 3, 1.3), + Edge(1, 4, 1.4), + Edge(1, 5, 1.5) + ) + } + + Then("adjacent of 3 should equal listOf(3->4:3.4)") { + graph.adjacentVertex(3) `should equal` listOf(Edge(3, 4, 3.4)) + } + } + + Scenario("reverse test") { + val diGraph by memoized { WeightDiGraph() } + + Given("directed graph 0->2:0.2, 0->4:0.4, 1->0:1.0, 1->2:1.2, 4->2:4.2") { + diGraph.addEdge(Edge(0, 2, 0.2)) + diGraph.addEdge(Edge(0, 4, 0.4)) + diGraph.addEdge(Edge(1, 0, 1.0)) + diGraph.addEdge(Edge(1, 2, 1.2)) + diGraph.addEdge(Edge(4, 2, 4.2)) + } + + lateinit var result: WeightDirectedGraph + + When("compute the reversed graph") { + result = diGraph.reverse() + } + + Then("adjacent of 0 should equals listOf(0->1:1.0)") { + result.adjacentVertex(0) `should equal` listOf(Edge(0, 1, 1.0)) + } + + Then("adjacent of 1 should be empty") { + result.adjacentVertex(1).isEmpty() `should be equal to` true + } + + Then("adjacent of 2 should equal listOf(2->0:0.2, 2->1:1.2, 2->4:4.2)") { + result.adjacentVertex(2).sorted() `should equal` listOf( + Edge(2, 0, 0.2), + Edge(2, 1, 1.2), + Edge(2, 4, 4.2) + ) + } + } + } +}) \ No newline at end of file diff --git a/src/test/kotlin/it/norangeb/algorithms/graph/WeightGraphTest.kt b/src/test/kotlin/it/norangeb/algorithms/graph/WeightGraphTest.kt new file mode 100644 index 0000000..7f9439d --- /dev/null +++ b/src/test/kotlin/it/norangeb/algorithms/graph/WeightGraphTest.kt @@ -0,0 +1,81 @@ +/* + * MIT License + * + * Copyright (c) 2019 norangebit + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package it.norangeb.algorithms.graph + +import it.norangeb.algorithms.graph.data.Edge +import org.amshove.kluent.`should be equal to` +import org.amshove.kluent.`should equal` +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.gherkin.Feature + +object WeightGraphTest : Spek({ + Feature("weight undirected graph") { + val graph by memoized { WeightGraph() } + + Scenario("add edges") { + When("add edge 1-4:5.0") { + graph.addEdge(Edge(1, 4, 5.0)) + } + + Then("number of edge should equal to 1") { + graph.edgeNumber() `should be equal to` 1 + } + + Then("adjacent of 1 should equal listOf(1-4:5.0)") { + graph.adjacentVertex(1) `should equal` listOf(Edge(1, 4, 5.0)) + } + + Then("adjacent of 4 should equal listOf(4-1:5.0)") { + graph.adjacentVertex(4) `should equal` listOf(Edge(4, 1, 5.0)) + } + + When("add edge 1-3:1.1, 3-4:3.4, 1-5:1.5") { + graph.addEdge(Edge(1, 3, 1.1)) + graph.addEdge(Edge(3, 4, 3.4)) + graph.addEdge(Edge(1, 5, 1.5)) + } + + Then("number of edge should equal to 4") { + graph.edgeNumber() `should be equal to` 4 + } + + Then("adjacent of 1 should equal listOf(1-3:1.1, 1-4:5.0, 1-5:1.5)") { + graph.adjacentVertex(1).sorted() `should equal` listOf( + Edge(1, 3, 1.1), + Edge(1, 5, 1.5), + Edge(1, 4, 5.0) + ) + } + + Then("adjacent of 3 should equal listOf(3-1:1.1, 3-4:3.4)") { + graph.adjacentVertex(3).sorted() `should equal` listOf( + Edge(3, 1, 1.1), + Edge(3, 4, 3.4) + ) + } + } + } +}) \ No newline at end of file diff --git a/src/test/kotlin/it/norangeb/algorithms/graph/data/WeightAdjacentListTest.kt b/src/test/kotlin/it/norangeb/algorithms/graph/data/WeightAdjacentListTest.kt new file mode 100644 index 0000000..53e8e06 --- /dev/null +++ b/src/test/kotlin/it/norangeb/algorithms/graph/data/WeightAdjacentListTest.kt @@ -0,0 +1,91 @@ +/* + * MIT License + * + * Copyright (c) 2019 norangebit + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package it.norangeb.algorithms.graph.data + +import org.amshove.kluent.`should be equal to` +import org.amshove.kluent.`should contain` +import org.amshove.kluent.`should equal` +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.gherkin.Feature + +object WeightAdjacentListTest : Spek({ + Feature("adjacent list graph data") { + val graphData by memoized { WeightAdjacentList() } + + Scenario("add edges") { + When("add edge 1 -> 7: 1.3") { + graphData.addEdge(Edge(1, 7, 1.3)) + } + + Then("adjacent of 1 should contains 7") { + graphData.adjacent(1) `should contain` Edge(1, 7, 1.3) + } + + Then("adjacent of 7 should be empty") { + graphData.adjacent(7).isEmpty() `should be equal to` true + } + + Then("edgeNumber should be equal to 1") { + graphData.edgeNumber() `should be equal to` 1 + } + + Then("vertexNumber should be equal to 8") { + graphData.vertexNumber() `should be equal to` 8 + } + + When("add edge 1 -> 8: 2.0, 7 -> 9: 4.3, 1 -> 3: 1.0, 3 -> 1: 3.4") { + graphData.addEdge(Edge(1, 8, 2.0)) + graphData.addEdge(Edge(7, 9, 4.3)) + graphData.addEdge(Edge(1, 3, 1.0)) + graphData.addEdge(Edge(3, 1, 3.4)) + } + + Then("adjacent of 1 should equal listOf(3, 7, 8)") { + graphData.adjacent(1).sorted() `should equal` listOf( + Edge(1, 3, 1.0), + Edge(1, 7, 1.3), + Edge(1, 8, 2.0) + ) + } + + Then("adjacent of 7 should equal listOf(9)") { + graphData.adjacent(7) `should equal` listOf(Edge(7, 9, 4.3)) + } + + Then("adjacent of 3 should equal listOf(1)") { + graphData.adjacent(3) `should equal` listOf(Edge(3, 1, 3.4)) + } + + Then("edgeNumber should be equal to 5") { + graphData.edgeNumber() `should be equal to` 5 + } + + Then("vertexNumber should be equal to 10") { + graphData.vertexNumber() `should be equal to` 10 + } + } + } +}) \ No newline at end of file diff --git a/src/test/kotlin/it/norangeb/algorithms/graph/data/WeightAdjacentMatrixTest.kt b/src/test/kotlin/it/norangeb/algorithms/graph/data/WeightAdjacentMatrixTest.kt new file mode 100644 index 0000000..7cf5fc3 --- /dev/null +++ b/src/test/kotlin/it/norangeb/algorithms/graph/data/WeightAdjacentMatrixTest.kt @@ -0,0 +1,91 @@ +/* + * MIT License + * + * Copyright (c) 2019 norangebit + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package it.norangeb.algorithms.graph.data + +import org.amshove.kluent.`should be equal to` +import org.amshove.kluent.`should contain` +import org.amshove.kluent.`should equal` +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.gherkin.Feature + +object WeightAdjacentMatrixTest : Spek({ + Feature("adjacent matrix graph data") { + val graphData by memoized { WeightAdjacentMatrix(10) } + + Scenario("add edges") { + When("add edge 1 -> 7: 1.3") { + graphData.addEdge(Edge(1, 7, 1.3)) + } + + Then("adjacent of 1 should contains 7") { + graphData.adjacent(1) `should contain` Edge(1, 7, 1.3) + } + + Then("adjacent of 7 should be empty") { + graphData.adjacent(7).isEmpty() `should be equal to` true + } + + Then("edgeNumber should be equal to 1") { + graphData.edgeNumber() `should be equal to` 1 + } + + Then("vertexNumber should be equal to 8") { + graphData.vertexNumber() `should be equal to` 10 + } + + When("add edge 1 -> 8: 2.0, 7 -> 9: 4.3, 1 -> 3: 1.0, 3 -> 1: 3.4") { + graphData.addEdge(Edge(1, 8, 2.0)) + graphData.addEdge(Edge(7, 9, 4.3)) + graphData.addEdge(Edge(1, 3, 1.0)) + graphData.addEdge(Edge(3, 1, 3.4)) + } + + Then("adjacent of 1 should equal listOf(3, 7, 8)") { + graphData.adjacent(1).sorted() `should equal` listOf( + Edge(1, 3, 1.0), + Edge(1, 7, 1.3), + Edge(1, 8, 2.0) + ) + } + + Then("adjacent of 7 should equal listOf(9)") { + graphData.adjacent(7) `should equal` listOf(Edge(7, 9, 4.3)) + } + + Then("adjacent of 3 should equal listOf(1)") { + graphData.adjacent(3) `should equal` listOf(Edge(3, 1, 3.4)) + } + + Then("edgeNumber should be equal to 5") { + graphData.edgeNumber() `should be equal to` 5 + } + + Then("vertexNumber should be equal to 10") { + graphData.vertexNumber() `should be equal to` 10 + } + } + } +}) \ No newline at end of file