Skip to content
This repository has been archived by the owner on Apr 26, 2019. It is now read-only.

Commit

Permalink
search: remove BreadthFirstSearch and DepthFirstSearch
Browse files Browse the repository at this point in the history
Both of these are easily implemented on top of the graph traversal
primitives in traverse.

Also:

1. BreadthFirstSearch here is built on AStar, which is a particularly
   heavy way to do this.
2. DepthFirstSearch here returns a path. Given the nature of the
   traversal this is almost always going to be not the path the client
   wants, so we should not deceive.
  • Loading branch information
kortschak committed May 28, 2015
1 parent da765af commit acedd2c
Show file tree
Hide file tree
Showing 2 changed files with 0 additions and 60 deletions.
46 changes: 0 additions & 46 deletions search/graph_search.go
Expand Up @@ -86,15 +86,6 @@ func AStar(start, goal graph.Node, g graph.Graph, cost graph.CostFunc, heuristic
return nil, 0, nodesExpanded
}

// BreadthFirstSearch finds a path with a minimal number of edges from from start to goal.
//
// BreadthFirstSearch returns the path found and the number of nodes visited in the search.
// The returned path is nil if no path exists.
func BreadthFirstSearch(start, goal graph.Node, g graph.Graph) ([]graph.Node, int) {
path, _, visited := AStar(start, goal, g, UniformCost, NullHeuristic)
return path, visited
}

// Dijkstra's Algorithm is essentially a goalless Uniform Cost Search. That is, its results are
// roughly equivalent to running A* with the Null Heuristic from a single node to every other node
// in the graph -- though it's a fair bit faster because running A* in that way will recompute
Expand Down Expand Up @@ -282,43 +273,6 @@ func Johnson(g graph.Graph, cost graph.CostFunc) (nodePaths map[int]map[int][]gr
return nodePaths, nodeCosts, nil
}

// Expands the first node it sees trying to find the destination. Depth First Search is *not*
// guaranteed to find the shortest path, however, if a path exists DFS is guaranteed to find it
// (provided you don't find a way to implement a Graph with an infinite depth.)
func DepthFirstSearch(start, goal graph.Node, g graph.Graph) []graph.Node {
sf := setupFuncs(g, nil, nil)
successors := sf.successors

closedSet := make(internal.IntSet)
predecessor := make(map[int]graph.Node)

openSet := internal.NodeStack{start}
for openSet.Len() != 0 {
curr := openSet.Pop()

if closedSet.Has(curr.ID()) {
continue
}

if curr.ID() == goal.ID() {
return rebuildPath(predecessor, goal)
}

closedSet.Add(curr.ID())

for _, neighbor := range successors(curr) {
if closedSet.Has(neighbor.ID()) {
continue
}

predecessor[neighbor.ID()] = curr
openSet.Push(neighbor)
}
}

return nil
}

// An admissible, consistent heuristic that won't speed up computation time at all.
func NullHeuristic(_, _ graph.Node) float64 {
return 0
Expand Down
14 changes: 0 additions & 14 deletions search/search_test.go
Expand Up @@ -147,20 +147,6 @@ func TestSmallAStar(t *testing.T) {
}
}

func ExampleBreadthFirstSearch() {
g := concrete.NewDirectedGraph()
var n0, n1, n2, n3 concrete.Node = 0, 1, 2, 3
g.AddDirectedEdge(concrete.Edge{n0, n1}, 1)
g.AddDirectedEdge(concrete.Edge{n0, n2}, 1)
g.AddDirectedEdge(concrete.Edge{n2, n3}, 1)
path, v := search.BreadthFirstSearch(n0, n3, g)
fmt.Println("path:", path)
fmt.Println("nodes visited:", v)
// Output:
// path: [0 2 3]
// nodes visited: 4
}

func newSmallGonumGraph() *concrete.Graph {
eds := []struct{ n1, n2, edgeCost int }{
{1, 2, 7},
Expand Down

0 comments on commit acedd2c

Please sign in to comment.