diff --git a/grapp/src/main/kotlin/fr/ulille/grapp/algorithm/observation/ODataStructures.kt b/grapp/src/main/kotlin/fr/ulille/grapp/algorithm/observation/ODataStructures.kt index 19b7e02dba614374a872365c19fc529cd48b472c..41db084e79c6d67069d666b84401a2127f0da06b 100644 --- a/grapp/src/main/kotlin/fr/ulille/grapp/algorithm/observation/ODataStructures.kt +++ b/grapp/src/main/kotlin/fr/ulille/grapp/algorithm/observation/ODataStructures.kt @@ -24,7 +24,6 @@ import kotlin.collections.ArrayList import kotlin.collections.LinkedHashMap import kotlin.collections.LinkedHashSet -// CLEAN interface ODataStructure : Observable /** A queue structure to be used in graph traversal algorithms. @@ -49,7 +48,7 @@ class Fifo<E: Any> () : TraversalQueue<E>() { override fun sqAddAbstract(e: E) = addLast(e) } -/** An observable version of the {@see TraversalQueue}, with offeringn two implementations Olifo and Ofifo. */ +/** An observable version of the {@see TraversalQueue}, offering two implementations OLifo and OFifo. */ abstract class OTraversalQueue<E:Any>() : TraversalQueue<E>(), Observable by ObservableImpl(), ODataStructure { override fun put (e: E) { diff --git a/grapp/src/main/kotlin/fr/ulille/grapp/algorithm/observation/Observation.kt b/grapp/src/main/kotlin/fr/ulille/grapp/algorithm/observation/Observation.kt index 0f92ebc63c97ac08dbcf68b58b739a78642b2b43..1ec8c6d11af9a006735eb808f0c9e9052aa17669 100644 --- a/grapp/src/main/kotlin/fr/ulille/grapp/algorithm/observation/Observation.kt +++ b/grapp/src/main/kotlin/fr/ulille/grapp/algorithm/observation/Observation.kt @@ -21,8 +21,6 @@ package fr.ulille.grapp.algorithm.observation import java.lang.IllegalArgumentException -// CLEAN - /** Notifies a unique {@see Observer} about some of its state changes. * The state changes are encoded by {@see Event}s. * Before observation can start, it must be initialized by #initObservation @@ -62,10 +60,8 @@ class ObservableImpl : Observable { /** Observes a number of {@see Observable}, for which an observation relation has been defined with this observer. * They can be accessed by the name of the observation relation. */ abstract class Observer { - val observed : Map<String,Observable> - init { - observed = mutableMapOf<String,Observable>() - } + val observed = mutableMapOf<String,Observable> () + /** Retrieves the observable with the given name. * @throws NoSuchElementException if no such observable is known */ diff --git a/grapp/src/main/kotlin/fr/ulille/grapp/exercices/graphgen/GridGraphGenerator.kt b/grapp/src/main/kotlin/fr/ulille/grapp/exercices/graphgen/GridGraphGenerator.kt new file mode 100644 index 0000000000000000000000000000000000000000..89e006d55c73d8d4e961a8e1357063c1d5b2bacd --- /dev/null +++ b/grapp/src/main/kotlin/fr/ulille/grapp/exercices/graphgen/GridGraphGenerator.kt @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2022 Iovka Boneva, Université de Lille + * + * This file is part of Grapp. + * + * Grapp is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Grapp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Grapp. If not, see <https://www.gnu.org/licenses/> + */ + +package fr.ulille.grapp.exercices.graphgen + +import fr.ulille.grapp.graph.Graph +import fr.ulille.grapp.graph.Graphs +import fr.ulille.grapp.graph.GrappType +import java.lang.IllegalArgumentException + +typealias NodeCoord = Pair<Int,Int> +typealias EdgeCoord = Pair<NodeCoord, NodeCoord> + +fun NodeCoord.x() = first +fun NodeCoord.y() = second +fun EdgeCoord.src() = first +fun EdgeCoord.tgt() = second + +/** Allows to generate a graph which nodes are letters "a", "b", ... and are arranged on a grid. */ +class GridGraphGenerator (val nbNodeLines : Int = 3, val nbNodeColumns : Int = 3) { + + private val lastNode = 'a' + (nbNodeLines * nbNodeColumns - 1) + private val xrange = IntRange(0, nbNodeLines-1) + private val yrange = IntRange(0, nbNodeColumns-1) + private val nodesRange = CharRange('a', lastNode) + + private fun toNode(nodeCoord: NodeCoord): String { + return "${('a'.code + (nodeCoord.x() * nbNodeColumns + nodeCoord.y())).toChar()}" + } + + private fun toCoordinates (node: Char) : NodeCoord { + val nodeRank = (node - 'a') + val x = nodeRank / nbNodeColumns + val y = nodeRank % nbNodeColumns + return Pair(x,y) + } + + private fun outgoingEdges (node: NodeCoord) : List<EdgeCoord> { + val result = mutableListOf<EdgeCoord>() + val (x,y) = node + for (i in -1 .. 1) + for (j in -1 .. 1) + if ((i!=0 || j!=0) && x+i in xrange && y+j in yrange) + result.add(EdgeCoord(node, NodeCoord(x + i, y + j))) + return result + } + + fun generateGraph (nbEdges: Int, grappType: GrappType) : Graph { + val maxPossibleNbEdges = nbNodeColumns*(nbNodeLines-1) + (nbNodeColumns-1)*nbNodeLines + (nbNodeColumns-1)*(nbNodeLines-1) + if (nbEdges > maxPossibleNbEdges) + throw IllegalArgumentException("Impossible to generate a graph with as many edges.") + + val allPossibleEdges = mutableSetOf<EdgeCoord>() + for (node in nodesRange) + allPossibleEdges.addAll(outgoingEdges(toCoordinates(node))) + + val edges = mutableListOf<EdgeCoord>() + + while (edges.size != nbEdges) { + val edge = allPossibleEdges.random() + allPossibleEdges.remove(edge) + if (canBeAdded(edge, edges)) + edges.add(edge) + } + + val values = if (grappType.isWeighted()) (1..nbEdges).map {it.toDouble()}.toMutableSet() else mutableSetOf() + val randomValue : () -> Double = { + val result = values.random() + values.remove(result) + result + } + + val graph = Graphs.graphFromNodeSet(grappType, nodesRange.map{ "$it" }.toList()) + for (edge in edges) { + if (grappType.isWeighted()) + Graphs.addEdge(graph, toNode(edge.src()), toNode(edge.tgt()), randomValue()) + else + Graphs.addEdge(graph, toNode(edge.src()), toNode(edge.tgt())) + } + return graph + } + + companion object { + private fun canBeAdded (edge: EdgeCoord, to: Collection<EdgeCoord>) : Boolean { + val isOpposite : (EdgeCoord, EdgeCoord) -> Boolean = { e1, e2 -> + e1.src() == e2.tgt() && e1.tgt() == e2.src() + } + for (e in to) + if (e == edge || isOpposite(edge,e) || areCrossing(edge,e)) + return false + return true + } + + private fun areCrossing (edge: EdgeCoord, anotherEdge: EdgeCoord) : Boolean { + + val topToBottom : (EdgeCoord) -> EdgeCoord = { e -> + if (e.src().x() > e.tgt().x()) + Pair(e.tgt(),e.src()) + else + Pair(e.src(), e.tgt()) + } + + val isDiagonalLeftToRight : (EdgeCoord) -> Boolean = { e -> + e.src().x() + 1 == e.tgt().x() && e.src().y() + 1 == e.tgt().y() + } + val isDiagonalRightToLeft : (EdgeCoord) -> Boolean = { e -> + e.src().x() + 1 == e.tgt().x() && e.src().y() == e.tgt().y() + 1 + } + + val sourcesAreSameLineNeighboursLeftAndRight : (EdgeCoord, EdgeCoord) -> Boolean = { e1, e2 -> + e1.src().x() == e2.src().x() && e1.src().y() + 1 == e2.src().y() + } + + val edge = topToBottom(edge) + val anotherEdge = topToBottom(anotherEdge) + + return sourcesAreSameLineNeighboursLeftAndRight(edge, anotherEdge) && + isDiagonalLeftToRight(edge) && isDiagonalRightToLeft(anotherEdge) + || + sourcesAreSameLineNeighboursLeftAndRight(anotherEdge, edge) && + isDiagonalLeftToRight(anotherEdge) && isDiagonalRightToLeft(edge) + } + } + +} diff --git a/grapp/src/main/kotlin/fr/ulille/grapp/exercices/traces/ShortestPathTraces.kt b/grapp/src/main/kotlin/fr/ulille/grapp/exercices/traces/ShortestPathTraces.kt new file mode 100644 index 0000000000000000000000000000000000000000..24cbfa2c8d8d60156beb8a3c9f9668476dcf3f6c --- /dev/null +++ b/grapp/src/main/kotlin/fr/ulille/grapp/exercices/traces/ShortestPathTraces.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 Iovka Boneva, Université de Lille + * + * This file is part of Grapp. + * + * Grapp is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Grapp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Grapp. If not, see <https://www.gnu.org/licenses/> + */ + +package fr.ulille.grapp.exercices.traces + +class ShortestPathTraces { + + +} \ No newline at end of file diff --git a/grapp/src/main/kotlin/fr/ulille/grapp/ui/Traces.kt b/grapp/src/main/kotlin/fr/ulille/grapp/ui/Traces.kt new file mode 100644 index 0000000000000000000000000000000000000000..bdc51c932977136afaaa329def0bda8789998f52 --- /dev/null +++ b/grapp/src/main/kotlin/fr/ulille/grapp/ui/Traces.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 Iovka Boneva, Université de Lille + * + * This file is part of Grapp. + * + * Grapp is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Grapp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Grapp. If not, see <https://www.gnu.org/licenses/> + */ + +package fr.ulille.grapp.ui + +class Traces { + + +} \ No newline at end of file diff --git a/grapp/src/test/kotlin/fr/ulille/grapp/algorithm/observation/TestObservation.kt b/grapp/src/test/kotlin/fr/ulille/grapp/algorithm/observation/TestObservation.kt index b1ce3a2944440e3be3904969e13e0e44b79ae27e..a7ae692542a832d61bd4dfd4d3a34e398aa74c2a 100644 --- a/grapp/src/test/kotlin/fr/ulille/grapp/algorithm/observation/TestObservation.kt +++ b/grapp/src/test/kotlin/fr/ulille/grapp/algorithm/observation/TestObservation.kt @@ -23,7 +23,6 @@ import org.junit.Test import java.lang.Exception import org.junit.Assert.* -// CLEAN class TestObservation { @Test diff --git a/grapp/src/test/kotlin/fr/ulille/grapp/exercices/graphgen/TestGridGraphGenerator.kt b/grapp/src/test/kotlin/fr/ulille/grapp/exercices/graphgen/TestGridGraphGenerator.kt new file mode 100644 index 0000000000000000000000000000000000000000..a6ba6a7a6a46e95f8e8b15a4ba9d63fd5f8f9daf --- /dev/null +++ b/grapp/src/test/kotlin/fr/ulille/grapp/exercices/graphgen/TestGridGraphGenerator.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 Iovka Boneva, Université de Lille + * + * This file is part of Grapp. + * + * Grapp is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Grapp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Grapp. If not, see <https://www.gnu.org/licenses/> + */ + +package fr.ulille.grapp.exercices.graphgen + +import fr.ulille.grapp.graph.GrappType +import kotlin.test.Test +import kotlin.test.assertEquals + +class TestGridGraphGenerator { + + @Test + fun testGridGraphGen () { + val gen3x4 = GridGraphGenerator(3, 4) + val graph = gen3x4.generateGraph(20, GrappType.uwgraph) + + assertEquals(setOf("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"), graph.vertexSet()) + assertEquals(20, graph.edgeSet().size) + assertEquals((1..20).map { it.toDouble() }.toSet(), graph.edgeSet().map{ it.weight }.toSet()) + } +} \ No newline at end of file diff --git a/grapp/src/test/kotlin/fr/ulille/grapp/io/TestYamlIOSerialization.kt b/grapp/src/test/kotlin/fr/ulille/grapp/io/TestYamlIOSerialization.kt index bc8dc9a920f63111c5938517cbb81a86d9e85576..42766c8504ffd98f63ae13e4e1d93e470c47d1dd 100644 --- a/grapp/src/test/kotlin/fr/ulille/grapp/io/TestYamlIOSerialization.kt +++ b/grapp/src/test/kotlin/fr/ulille/grapp/io/TestYamlIOSerialization.kt @@ -34,7 +34,7 @@ class TestYamlIOSerialization { edges: a: [b, c] b: [c] - c: [d, a] + c: [a, d] d: [] """.trimIndent() val g = YamlParser.parse(s.byteInputStream()) @@ -95,7 +95,7 @@ class TestYamlIOSerialization { wedges: a: {b: 1, c: 2} b: {c: -3} - c: {d: 4, a: 5} + c: {a: 5, d: 4} d: {} """.trimIndent() assertEquals(sWithNormalizedGrappType.trim(), o.toString().trim()) diff --git a/grapp/src/test/kotlin/fr/ulille/grapp/ui/TestAlgorithmsUtil.kt b/grapp/src/test/kotlin/fr/ulille/grapp/ui/TestAlgorithmsUtil.kt index 07418e9824af5b2d6ac5059d44443f1a2f1346ac..bec6bef8a52f2259c81b3d740d8b3eb948c063f7 100644 --- a/grapp/src/test/kotlin/fr/ulille/grapp/ui/TestAlgorithmsUtil.kt +++ b/grapp/src/test/kotlin/fr/ulille/grapp/ui/TestAlgorithmsUtil.kt @@ -177,11 +177,11 @@ class TestAlgorithmsUtil { ShortestPathAlgorithmName.Dijkstra, g, "a" ) val p = AlgorithmsUtil.runFindPathAlgorithm(r, "a", "b") - assertEquals(2, p.pathEdges.size) - assertEquals("a", p.pathEdges[0].src) - assertEquals("c", p.pathEdges[0].tgt) - assertEquals("c", p.pathEdges[1].src) - assertEquals("b", p.pathEdges[1].tgt) + assertEquals(2, p.pathEdges!!.size) + assertEquals("a", p.pathEdges!![0].src) + assertEquals("c", p.pathEdges!![0].tgt) + assertEquals("c", p.pathEdges!![1].src) + assertEquals("b", p.pathEdges!![1].tgt) } @Test @@ -191,9 +191,9 @@ class TestAlgorithmsUtil { ShortestPathAlgorithmName.Dijkstra, g, "c" ) val p = AlgorithmsUtil.runFindPathAlgorithm(r, "c", "a") - assertEquals(1, p.pathEdges.size) - assertEquals("c", p.pathEdges[0].src) - assertEquals("a", p.pathEdges[0].tgt) + assertEquals(1, p.pathEdges!!.size) + assertEquals("c", p.pathEdges!![0].src) + assertEquals("a", p.pathEdges!![0].tgt) } @Test @@ -203,7 +203,7 @@ class TestAlgorithmsUtil { ShortestPathAlgorithmName.Dijkstra, g, "a" ) val p = AlgorithmsUtil.runFindPathAlgorithm(r, "f", "d") - assertEquals(0, p.pathEdges.size) + assertNull(p.pathEdges) } @Test @@ -213,11 +213,11 @@ class TestAlgorithmsUtil { TraversalAlgorithmName.DFS, g, "a" ) val p = AlgorithmsUtil.runFindPathAlgorithm(r, "a", "c") - assertEquals(2, p.pathEdges.size) - assertEquals("a", p.pathEdges[0].src) - assertEquals("b", p.pathEdges[0].tgt) - assertEquals("b", p.pathEdges[1].src) - assertEquals("c", p.pathEdges[1].tgt) + assertEquals(2, p.pathEdges!!.size) + assertEquals("a", p.pathEdges!![0].src) + assertEquals("b", p.pathEdges!![0].tgt) + assertEquals("b", p.pathEdges!![1].src) + assertEquals("c", p.pathEdges!![1].tgt) } @Test @@ -241,7 +241,7 @@ class TestAlgorithmsUtil { TraversalAlgorithmName.DFS, g, "a" ) val p = AlgorithmsUtil.runFindPathAlgorithm(r, "e", "f") - assertEquals(0, p.pathEdges.size) + assertNull(p.pathEdges) } @Test