diff --git a/modules/core/src/main/scala/gs/graph/v0/directed/Dag.scala b/modules/core/src/main/scala/gs/graph/v0/directed/Dag.scala index 3a25bf0..355d8e5 100644 --- a/modules/core/src/main/scala/gs/graph/v0/directed/Dag.scala +++ b/modules/core/src/main/scala/gs/graph/v0/directed/Dag.scala @@ -18,6 +18,10 @@ class Dag protected ( object Dag: + given CanEqual[Dag, Dag] = CanEqual.derived + given CanEqual[Dag, Digraph] = CanEqual.derived + given CanEqual[Digraph, Dag] = CanEqual.derived + /** Validate that the input [[Digraph]] is a DAG. * * @param digraph @@ -26,7 +30,7 @@ object Dag: * The DAG instance, or an error if the input contained a cycle. */ def validate(digraph: Digraph): Either[GraphError, Dag] = - if Digraph.hasCycle(digraph) then + if !Digraph.hasCycle(digraph) then Right( new Dag(digraph.numberOfVertices, digraph.adjacency, digraph.roots) ) diff --git a/modules/core/src/main/scala/gs/graph/v0/directed/Digraph.scala b/modules/core/src/main/scala/gs/graph/v0/directed/Digraph.scala index 318e94d..9ef9cd2 100644 --- a/modules/core/src/main/scala/gs/graph/v0/directed/Digraph.scala +++ b/modules/core/src/main/scala/gs/graph/v0/directed/Digraph.scala @@ -21,10 +21,26 @@ class Digraph( val adjacency: Adjacency, val roots: Vector[Vertex] ) extends Graph: + /** @inheritDocs + */ override val disposition: GraphDisposition = GraphDisposition.Directed + override def equals(that: Any): Boolean = + that match + case other: Digraph => + numberOfVertices == other.numberOfVertices + && adjacency == other.adjacency + && roots.sameElements(other.roots) + case _ => false + +end Digraph + object Digraph: + given CanEqual[Digraph, Digraph] = CanEqual.derived + + def empty(): Digraph = new Digraph(Size.Zero, Adjacency.Empty, Vector.empty) + def fromEdges( numberOfVertices: Size, edges: Iterable[Edge] @@ -85,8 +101,9 @@ object Digraph: */ def hasCycle(digraph: Digraph): Boolean = digraph match - case _: Dag => false - case _ => new CycleDetector(digraph).hasCycle + case _ if digraph.isEmpty => false + case _: Dag => false + case _ => new CycleDetector(digraph).hasCycle // Internal class for finding cycles. // This implementation comes (roughly) from Algorithms (Fourth Edition) by diff --git a/modules/core/src/test/scala/gs/graph/v0/directed/DagTests.scala b/modules/core/src/test/scala/gs/graph/v0/directed/DagTests.scala new file mode 100644 index 0000000..115e998 --- /dev/null +++ b/modules/core/src/test/scala/gs/graph/v0/directed/DagTests.scala @@ -0,0 +1,11 @@ +package gs.graph.v0.directed + +import munit.* + +class DagTests extends FunSuite: + + test("should validate an empty graph") { + Dag.validate(Digraph.empty()) match + case Right(dag) => assertEquals(dag, Digraph.empty()) + case _ => fail("Expected the empty graph to be validated as a DAG.") + }