Skip to content

Commit

Permalink
Simplify graph tests by implicitly converting tuples to edges
Browse files Browse the repository at this point in the history
  • Loading branch information
Abhijit Sarkar committed Jan 16, 2025
1 parent 3f9311c commit 977ea25
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 38 deletions.
12 changes: 7 additions & 5 deletions graph/test/src/P83Spec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import org.scalatest.funspec.AnyFunSpec
import org.scalatest.matchers.should.Matchers.*
import P83.spanningTrees
import org.scalactic.Equality
import graph.Util.given
import scala.language.implicitConversions

class P83Spec extends AnyFunSpec:
it("construct all spanning trees"):
val data = List(
val data: List[(List[Char], List[Edge[Char, Nothing]])] = List(
(
List('a', 'b', 'c'),
List(('a', 'b'), ('b', 'c'), ('a', 'c'))
Expand All @@ -30,16 +32,16 @@ class P83Spec extends AnyFunSpec:
)
)

val edgeEq = new Equality[(Char, Char)]:
def areEqual(a: (Char, Char), b: Any): Boolean =
val edgeEq = new Equality[Edge[Char, Nothing]]:
def areEqual(a: Edge[Char, Nothing], b: Any): Boolean =
if b.isInstanceOf[List[?]] then
b.asInstanceOf[List[Char]] match
case u :: v :: Nil => (u, v) == a || (v, u) == a
case u :: v :: Nil => (u, v) == (a.u, a.v) || (v, u) == (a.u, a.v)
case _ => false
else false

data.foreach { (vertices, edges) =>
val g = Graph.buildUG(vertices, edges.map((u, v) => Edge(u, v, None)))
val g = Graph.buildUG(vertices, edges)
val st = g.spanningTrees
val n = g.vertices.size
st.foreach { t =>
Expand Down
14 changes: 8 additions & 6 deletions graph/test/src/P84Spec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import org.scalatest.funspec.AnyFunSpec
import org.scalatest.matchers.should.Matchers.*
import P84.minimalSpanningTree
import org.scalactic.Equality
import graph.Util.given
import scala.language.implicitConversions

class P84Spec extends AnyFunSpec:
it("construct the minimal spanning tree"):
val data = List(
val data: List[(List[Char], List[Edge[Char, Int]], Int)] = List(
(
List('a', 'b', 'c'),
List(('a', 'b', 1), ('b', 'c', 2), ('a', 'c', 3)),
Expand All @@ -32,15 +34,15 @@ class P84Spec extends AnyFunSpec:
)
)

val edgeEq = new Equality[(Char, Char, Int)]:
def areEqual(a: (Char, Char, Int), b: Any): Boolean =
val edgeEq = new Equality[Edge[Char, Int]]:
def areEqual(a: Edge[Char, Int], b: Any): Boolean =
if b.isInstanceOf[Edge[?, ?]] then
val e = b.asInstanceOf[Edge[Char, Int]]
(a._1, a._2) == (e.u, e.v) || (a._1, a._2) == (e.v, e.u)
b.asInstanceOf[Edge[Char, Int]] match
case Edge(u, v, _) => (u, v) == (a.u, a.v) || (v, u) == (a.u, a.v)
else false

data.foreach { (vertices, edges, cost) =>
val g = Graph.buildUG(vertices, edges.map((u, v, d) => Edge(u, v, Some(d))))
val g = Graph.buildUG(vertices, edges)
val mst = g.minimalSpanningTree
mst.foreach(e => (edges should contain(e))(edgeEq))
mst.foldLeft(0)((s, e) => s + e.data.getOrElse(0)) shouldBe cost
Expand Down
58 changes: 33 additions & 25 deletions graph/test/src/P85Spec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,68 +3,76 @@ package graph
import org.scalatest.funspec.AnyFunSpec
import org.scalatest.matchers.should.Matchers.shouldBe
import P85.isIsomorphicTo
import graph.Util.given
import scala.language.implicitConversions

class P85Spec extends AnyFunSpec:
it("graph isomorphism"):

val v1 = List('a', 'b')
val e1 = List(('a', 'b'))
val v2 = List(5, 7)
val e2 = List((5, 7))
val g1 = Graph.buildUG(v1, e1.map((u, v) => Edge(u, v, None)))
val g2 = Graph.buildUG(v2, e2.map((u, v) => Edge(u, v, None)))
val v1 = List('a', 'b')
val e1: List[Edge[Char, Nothing]] = List(('a', 'b'))
val v2 = List(5, 7)
val e2: List[Edge[Int, Nothing]] = List((5, 7))
val g1 = Graph.buildUG(v1, e1)
val g2 = Graph.buildUG(v2, e2)
g1.isIsomorphicTo(g2) shouldBe true

// format: off
val v3 = (1 to 8).toList
val e3 =
val e3: List[Edge[Int, Nothing]] =
List(
(1, 5), (1, 6), (1, 7), (2, 5),
(2, 6), (2, 8), (3, 5), (3, 7),
(3, 8), (4, 6), (4, 7), (4, 8)
)
val e4 =
val e4: List[Edge[Int, Nothing]] =
List(
(1, 2), (1, 4), (1, 5), (6, 2),
(6, 5), (6, 7), (8, 4), (8, 5),
(8, 7), (3, 2), (3, 4), (3, 7)
)
// format: on

val g3 = Graph.buildUG(v3, e3.map((u, v) => Edge(u, v, None)))
val g4 = Graph.buildUG(v3, e4.map((u, v) => Edge(u, v, None)))
val g3 = Graph.buildUG(v3, e3)
val g4 = Graph.buildUG(v3, e4)
g3.isIsomorphicTo(g4) shouldBe true

val v5 = ('a' to 'e').toList
val e5 = List(('a', 'b'), ('a', 'c'), ('a', 'e'), ('b', 'c'), ('c', 'd'), ('d', 'e'))
val e5: List[Edge[Char, Nothing]] =
List(('a', 'b'), ('a', 'c'), ('a', 'e'), ('b', 'c'), ('c', 'd'), ('d', 'e'))
val v6 = ('A' to 'E').toList
val e6 = List(('A', 'D'), ('A', 'E'), ('B', 'C'), ('B', 'D'), ('B', 'E'), ('C', 'D'))
val e6: List[Edge[Char, Nothing]] =
List(('A', 'D'), ('A', 'E'), ('B', 'C'), ('B', 'D'), ('B', 'E'), ('C', 'D'))

val g5 = Graph.buildUG(v5, e5.map((u, v) => Edge(u, v, None)))
val g6 = Graph.buildUG(v6, e6.map((u, v) => Edge(u, v, None)))
val g5 = Graph.buildUG(v5, e5)
val g6 = Graph.buildUG(v6, e6)
g5.isIsomorphicTo(g6) shouldBe true

val v7 = List('α', 'β', 'γ', 'δ', 'ε')
val e7 = List(('α', 'β'), ('α', 'γ'), ('α', 'ε'), ('β', 'δ'), ('γ', 'δ'), ('δ', 'ε'))
val g7 = Graph.buildUG(v7, e7.map((u, v) => Edge(u, v, None)))
val e7: List[Edge[Char, Nothing]] =
List(('α', 'β'), ('α', 'γ'), ('α', 'ε'), ('β', 'δ'), ('γ', 'δ'), ('δ', 'ε'))
val g7 = Graph.buildUG(v7, e7)
g5.isIsomorphicTo(g7) shouldBe false
g6.isIsomorphicTo(g7) shouldBe false

val v8 = ('a' to 'f').toList
val e8 = List(('a', 'b'), ('a', 'd'), ('b', 'c'), ('c', 'f'), ('d', 'e'), ('e', 'f'))
val e9 = List(('a', 'd'), ('a', 'e'), ('b', 'd'), ('b', 'f'), ('c', 'e'), ('c', 'f'))
val g8 = Graph.buildUG(v8, e8.map((u, v) => Edge(u, v, None)))
val g9 = Graph.buildUG(v8, e9.map((u, v) => Edge(u, v, None)))
val e8: List[Edge[Char, Nothing]] =
List(('a', 'b'), ('a', 'd'), ('b', 'c'), ('c', 'f'), ('d', 'e'), ('e', 'f'))
val e9: List[Edge[Char, Nothing]] =
List(('a', 'd'), ('a', 'e'), ('b', 'd'), ('b', 'f'), ('c', 'e'), ('c', 'f'))
val g8 = Graph.buildUG(v8, e8)
val g9 = Graph.buildUG(v8, e9)
g8.isIsomorphicTo(g9) shouldBe true

// G(v8 e8) and G(va ea) are not isomorphic but the algorithm can't determine that.
// val va = [1..6]
// val ea = [(1, 3), (1, 5), (2, 4), (2, 6), (3, 5), (4, 6)]

val v10 = ('A' to 'D').toList
val e10 = List(('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'C'), ('B', 'D'), ('C', 'D'))
val v11 = (1 to 4).toList
val e11 = List((1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4))
val g10 = Graph.buildUG(v10, e10.map((u, v) => Edge(u, v, None)))
val g11 = Graph.buildUG(v11, e11.map((u, v) => Edge(u, v, None)))
val e10: List[Edge[Char, Nothing]] =
List(('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'C'), ('B', 'D'), ('C', 'D'))
val v11 = (1 to 4).toList
val e11: List[Edge[Int, Nothing]] = List((1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4))
val g10 = Graph.buildUG(v10, e10)
val g11 = Graph.buildUG(v11, e11)
g10.isIsomorphicTo(g11) shouldBe true
6 changes: 4 additions & 2 deletions graph/test/src/P86Spec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package graph
import org.scalatest.funspec.AnyFunSpec
import org.scalatest.matchers.should.Matchers.*
import P86.colorNodes
import graph.Util.given
import scala.language.implicitConversions

class P86Spec extends AnyFunSpec:
it("graph coloration"):
val data = List(
val data: List[(List[Char], List[Edge[Char, Nothing]])] = List(
(
('a' to 'j').toList,
List(
Expand Down Expand Up @@ -50,7 +52,7 @@ class P86Spec extends AnyFunSpec:
)

data.foreach { (vertices, edges) =>
val g = Graph.buildUG(vertices, edges.map((u, v) => Edge(u, v, None)))
val g = Graph.buildUG(vertices, edges)
val clrMap = g.colorNodes.toMap
vertices.foreach { u =>
g.neighbors(u).map(v => clrMap(v._1)) should not contain (clrMap(u))
Expand Down
7 changes: 7 additions & 0 deletions graph/test/src/Util.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package graph

object Util:
given [A, B] => Conversion[Tuple, Edge[A, B]] =
case (u, v) => Edge(u.asInstanceOf[A], v.asInstanceOf[A], None)
case (u, v, d) => Edge(u.asInstanceOf[A], v.asInstanceOf[A], Some(d.asInstanceOf[B]))
case _ => throw IllegalArgumentException(s"unsupported tuple")

0 comments on commit 977ea25

Please sign in to comment.