123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- // Copyright ©2014 The Gonum Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package topo
- import (
- "gonum.org/v1/gonum/graph"
- "gonum.org/v1/gonum/graph/traverse"
- )
- // IsPathIn returns whether path is a path in g.
- //
- // As special cases, IsPathIn returns true for a zero length path or for
- // a path of length 1 when the node in path exists in the graph.
- func IsPathIn(g graph.Graph, path []graph.Node) bool {
- switch len(path) {
- case 0:
- return true
- case 1:
- return g.Node(path[0].ID()) != nil
- default:
- var canReach func(uid, vid int64) bool
- switch g := g.(type) {
- case graph.Directed:
- canReach = g.HasEdgeFromTo
- default:
- canReach = g.HasEdgeBetween
- }
- for i, u := range path[:len(path)-1] {
- if !canReach(u.ID(), path[i+1].ID()) {
- return false
- }
- }
- return true
- }
- }
- // PathExistsIn returns whether there is a path in g starting at from extending
- // to to.
- //
- // PathExistsIn exists as a helper function. If many tests for path existence
- // are being performed, other approaches will be more efficient.
- func PathExistsIn(g graph.Graph, from, to graph.Node) bool {
- var t traverse.BreadthFirst
- return t.Walk(g, from, func(n graph.Node, _ int) bool { return n.ID() == to.ID() }) != nil
- }
- // ConnectedComponents returns the connected components of the undirected graph g.
- func ConnectedComponents(g graph.Undirected) [][]graph.Node {
- var (
- w traverse.DepthFirst
- c []graph.Node
- cc [][]graph.Node
- )
- during := func(n graph.Node) {
- c = append(c, n)
- }
- after := func() {
- cc = append(cc, []graph.Node(nil))
- cc[len(cc)-1] = append(cc[len(cc)-1], c...)
- c = c[:0]
- }
- w.WalkAll(g, nil, after, during)
- return cc
- }
|