【发布时间】:2020-03-06 15:34:46
【问题描述】:
我在 Kotlin 中有以下有向图的定义。 (我还在学习 Kotlin,所以请原谅任何不足之处。欢迎改进和提出建议。)我的目标是有一个方法,reverse,它保持顶点和循环,但交换其他边的方向。
// We use an edge list because it makes it the easiest to swap.
data class ReversibleDirectedGraph<T>(val vertices: Set<T>, val edgeList: List<Pair<T,T>>) {
// This should be a self-inverting function.
fun reverse(): ReversibleDirectedGraph<T> {
// Make sure all vertices in edgeList are in vertices.
val allVertices = edgeList.flatMap { it.toList() }
require(allVertices.all { it in vertices }) { "Illegal graph specification" }
// Swap the edges.
val newEdgeList = edgeList.map { it.second to it.first }
return ReversibleDirectedGraph(allVertices.toSet(), newEdgeList)
}
}
fun main() {
// Example test: works correctly. Double edge reversal results in original graph.
val g = ReversibleDirectedGraph(setOf(0, 1, 2, 3),
listOf(0 to 1, 2 to 1, 3 to 2, 3 to 0, 1 to 3))
println(g)
val gr = g.reverse()
println(gr)
val grr = gr.reverse()
println(grr)
println(grr == g)
}
我想使用基于属性的测试来使用 KotinTest 测试此代码,但我在构建它以正确生成无向图的随机样本时遇到了麻烦。如果我能做到这一点,我可以将边缘方向反转两次,然后确保达到原图。
我熟悉 Gen.list、Gen.choose 等,但我似乎无法将这些部分组合在一起以获得最终产品,即随机无向图。
我已经解决了这个问题,但这显然缺少部分,我希望有人可以提供帮助。我怀疑我可以在 Scala 中做到这一点,因为我在那里有更多经验,但我决心学习 Kotlin。最终,大致如下:
class ReversibleDirectedGraphTest: StringSpec() {
init {
"reversibleDirectedGraphTest" {
forAll { g: ReversibleDirectedGraph<Int> ->
assertEqual(g.reverse().reverse() == g) }
}
}
}
}
任何帮助/建议将不胜感激。谢谢!
【问题讨论】:
-
我假设 ReversibleDirectedGraph 是一个递归结构。这通常需要一个递归生成器。你能展示 RDG 的构造函数或工厂吗?那我也许可以提出一些具体的建议。
-
嗨,johanneslink。不需要递归:它只是一个基本的图形表示,包括一个顶点列表,然后是一个边列表,所以我想做的是生成一个顶点:List
,然后是一个边:List > 其中对中的 Ints 来自顶点列表。 -
你可以写一个 Gen> 或其他东西,它在里面从随机值生成一个图。那么你只需要将它传递给 forAll 方法?
-
@monkjack 这似乎是我需要采取的一步,但现在我发现我的生成器没有使用,并且出现异常“无法推断 dcp.day218.ReversibleDirectedGraph 的生成器;明确指定生成器。”有没有办法将生成器指定为隐式?
-
不像隐式不,Kotlin 没有像 scala 这样的隐式。您可以将它显式传递给 forAll。类似
forAll(MyCustomGen) { graph -> // test graph here }
标签: unit-testing kotlin property-based-testing kotlintest