This commit is contained in:
parent
4788240666
commit
f185bed5f5
3 changed files with 35 additions and 3 deletions
|
|
@ -18,6 +18,10 @@ class Dag protected (
|
||||||
|
|
||||||
object Dag:
|
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.
|
/** Validate that the input [[Digraph]] is a DAG.
|
||||||
*
|
*
|
||||||
* @param digraph
|
* @param digraph
|
||||||
|
|
@ -26,7 +30,7 @@ object Dag:
|
||||||
* The DAG instance, or an error if the input contained a cycle.
|
* The DAG instance, or an error if the input contained a cycle.
|
||||||
*/
|
*/
|
||||||
def validate(digraph: Digraph): Either[GraphError, Dag] =
|
def validate(digraph: Digraph): Either[GraphError, Dag] =
|
||||||
if Digraph.hasCycle(digraph) then
|
if !Digraph.hasCycle(digraph) then
|
||||||
Right(
|
Right(
|
||||||
new Dag(digraph.numberOfVertices, digraph.adjacency, digraph.roots)
|
new Dag(digraph.numberOfVertices, digraph.adjacency, digraph.roots)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,26 @@ class Digraph(
|
||||||
val adjacency: Adjacency,
|
val adjacency: Adjacency,
|
||||||
val roots: Vector[Vertex]
|
val roots: Vector[Vertex]
|
||||||
) extends Graph:
|
) extends Graph:
|
||||||
|
/** @inheritDocs
|
||||||
|
*/
|
||||||
override val disposition: GraphDisposition = GraphDisposition.Directed
|
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:
|
object Digraph:
|
||||||
|
|
||||||
|
given CanEqual[Digraph, Digraph] = CanEqual.derived
|
||||||
|
|
||||||
|
def empty(): Digraph = new Digraph(Size.Zero, Adjacency.Empty, Vector.empty)
|
||||||
|
|
||||||
def fromEdges(
|
def fromEdges(
|
||||||
numberOfVertices: Size,
|
numberOfVertices: Size,
|
||||||
edges: Iterable[Edge]
|
edges: Iterable[Edge]
|
||||||
|
|
@ -85,8 +101,9 @@ object Digraph:
|
||||||
*/
|
*/
|
||||||
def hasCycle(digraph: Digraph): Boolean =
|
def hasCycle(digraph: Digraph): Boolean =
|
||||||
digraph match
|
digraph match
|
||||||
case _: Dag => false
|
case _ if digraph.isEmpty => false
|
||||||
case _ => new CycleDetector(digraph).hasCycle
|
case _: Dag => false
|
||||||
|
case _ => new CycleDetector(digraph).hasCycle
|
||||||
|
|
||||||
// Internal class for finding cycles.
|
// Internal class for finding cycles.
|
||||||
// This implementation comes (roughly) from Algorithms (Fourth Edition) by
|
// This implementation comes (roughly) from Algorithms (Fourth Edition) by
|
||||||
|
|
|
||||||
|
|
@ -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.")
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue