dag: Validate for DAGs
This commit is contained in:
parent
e94c43e0dc
commit
d59ced3c57
20
dag/dag.go
20
dag/dag.go
|
@ -37,6 +37,26 @@ func (g *AcyclicGraph) Root() (Vertex, error) {
|
|||
return roots[0], nil
|
||||
}
|
||||
|
||||
// Validate validates the DAG. A DAG is valid if it has a single root
|
||||
// with no cycles.
|
||||
func (g *AcyclicGraph) Validate() error {
|
||||
if _, err := g.Root(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var cycles [][]Vertex
|
||||
for _, cycle := range StronglyConnected(&g.Graph) {
|
||||
if len(cycle) > 1 {
|
||||
cycles = append(cycles, cycle)
|
||||
}
|
||||
}
|
||||
if len(cycles) > 0 {
|
||||
return fmt.Errorf("cycles: %#v", cycles)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Walk walks the graph, calling your callback as each node is visited.
|
||||
// This will walk nodes in parallel if it can.
|
||||
func (g *AcyclicGraph) Walk(cb WalkFunc) error {
|
||||
|
|
|
@ -47,6 +47,34 @@ func TestAcyclicGraphRoot_multiple(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestAcyclicGraphValidate(t *testing.T) {
|
||||
var g AcyclicGraph
|
||||
g.Add(1)
|
||||
g.Add(2)
|
||||
g.Add(3)
|
||||
g.Connect(BasicEdge(3, 2))
|
||||
g.Connect(BasicEdge(3, 1))
|
||||
|
||||
if err := g.Validate(); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAcyclicGraphValidate_cycle(t *testing.T) {
|
||||
var g AcyclicGraph
|
||||
g.Add(1)
|
||||
g.Add(2)
|
||||
g.Add(3)
|
||||
g.Connect(BasicEdge(3, 2))
|
||||
g.Connect(BasicEdge(3, 1))
|
||||
g.Connect(BasicEdge(1, 2))
|
||||
g.Connect(BasicEdge(2, 1))
|
||||
|
||||
if err := g.Validate(); err == nil {
|
||||
t.Fatal("should error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAcyclicGraphWalk(t *testing.T) {
|
||||
var g AcyclicGraph
|
||||
g.Add(1)
|
||||
|
|
|
@ -58,7 +58,7 @@ func strongConnect(g *Graph, v Vertex, data *tarjanData) *tarjanVertex {
|
|||
|
||||
if tv.Lowlink == index {
|
||||
vs := make([]Vertex, 0, 2)
|
||||
for i := len(data.stack) - 1; ; i-- {
|
||||
for i := len(data.stack) - 1; i >= 0; i-- {
|
||||
v := data.stack[i]
|
||||
data.stack[i] = nil
|
||||
data.stack = data.stack[:i]
|
||||
|
|
Loading…
Reference in New Issue