From 203df0bf5c0e69967188ee3cc6182a12a123db17 Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 02:57:44 -0700 Subject: [PATCH 01/19] Added a cost function --- graph.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/graph.go b/graph.go index d33c7ec8..74baba04 100644 --- a/graph.go +++ b/graph.go @@ -120,3 +120,6 @@ type DStarGraph interface { Move(target Node) ChangedEdges() (newCostFunc func(Node, Node) float64, changedEdges []Edge) } + +// A function that returns the cost from one node to another +type CostFun func(Node, Node) float64 From a5c25df8d630d8a49ee65c4eb6901f2c567b2636 Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:00:16 -0700 Subject: [PATCH 02/19] Updated AStar --- search/graphSearch.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/search/graphSearch.go b/search/graphSearch.go index ecea06d8..0c67572c 100644 --- a/search/graphSearch.go +++ b/search/graphSearch.go @@ -30,13 +30,13 @@ import ( // To run Uniform Cost Search, run A* with the NullHeuristic // // To run Breadth First Search, run A* with both the NullHeuristic and UniformCost (or any cost function that returns a uniform positive value) -func AStar(start, goal gr.Node, graph gr.Graph, Cost, HeuristicCost func(gr.Node, gr.Node) float64) (path []gr.Node, cost float64, nodesExpanded int) { - successors, _, _, _, _, _, Cost, HeuristicCost := setupFuncs(graph, Cost, HeuristicCost) +func AStar(start, goal gr.Node, graph gr.Graph, cost, heuristicCost gr.CostFun) (path []gr.Node, pathCost float64, nodesExpanded int) { + successors, _, _, _, _, _, cost, heuristicCost := setupFuncs(graph, cost, heuristicCost) closedSet := make(map[int]internalNode) openSet := &aStarPriorityQueue{nodes: make([]internalNode, 0), indexList: make(map[int]int)} heap.Init(openSet) - node := internalNode{start, 0, HeuristicCost(start, goal)} + node := internalNode{start, 0, heuristicCost(start, goal)} heap.Push(openSet, node) predecessor := make(map[int]gr.Node) @@ -56,15 +56,15 @@ func AStar(start, goal gr.Node, graph gr.Graph, Cost, HeuristicCost func(gr.Node continue } - g := curr.gscore + Cost(curr.Node, neighbor) + g := curr.gscore + cost(curr.Node, neighbor) if existing, exists := openSet.Find(neighbor.ID()); !exists { predecessor[neighbor.ID()] = curr - node = internalNode{neighbor, g, g + HeuristicCost(neighbor, goal)} + node = internalNode{neighbor, g, g + heuristicCost(neighbor, goal)} heap.Push(openSet, node) } else if g < existing.gscore { predecessor[neighbor.ID()] = curr - openSet.Fix(neighbor.ID(), g, g+HeuristicCost(neighbor, goal)) + openSet.Fix(neighbor.ID(), g, g+heuristicCost(neighbor, goal)) } } } From 8c477930f7333e342a9975bf1b5621f73454b33c Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:01:15 -0700 Subject: [PATCH 03/19] Updated Dijkstra --- search/graphSearch.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/search/graphSearch.go b/search/graphSearch.go index 0c67572c..e1ea5169 100644 --- a/search/graphSearch.go +++ b/search/graphSearch.go @@ -89,8 +89,8 @@ func BreadthFirstSearch(start, goal gr.Node, graph gr.Graph) ([]gr.Node, int) { // Like A*, Dijkstra's Algorithm likely won't run correctly with negative edge weights -- use Bellman-Ford for that instead // // Dijkstra's algorithm usually only returns a cost map, however, since the data is available this version will also reconstruct the path to every node -func Dijkstra(source gr.Node, graph gr.Graph, Cost func(gr.Node, gr.Node) float64) (paths map[int][]gr.Node, costs map[int]float64) { - successors, _, _, _, _, _, Cost, _ := setupFuncs(graph, Cost, nil) +func Dijkstra(source gr.Node, graph gr.Graph, cost gr.CostFun) (paths map[int][]gr.Node, costs map[int]float64) { + successors, _, _, _, _, _, cost, _ := setupFuncs(graph, cost, nil) nodes := graph.NodeList() openSet := &aStarPriorityQueue{nodes: make([]internalNode, 0), indexList: make(map[int]int)} @@ -111,7 +111,7 @@ func Dijkstra(source gr.Node, graph gr.Graph, Cost func(gr.Node, gr.Node) float6 closedSet.Add(node.ID()) for _, neighbor := range successors(node) { - tmpCost := costs[node.ID()] + Cost(node, neighbor) + tmpCost := costs[node.ID()] + cost(node, neighbor) if cost, ok := costs[neighbor.ID()]; !ok { costs[neighbor.ID()] = tmpCost predecessor[neighbor.ID()] = node From 889f0dc83371736072024a69a9d7a26be0a08a78 Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:02:08 -0700 Subject: [PATCH 04/19] Updated Bellman-Ford --- search/graphSearch.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/search/graphSearch.go b/search/graphSearch.go index e1ea5169..d7527d87 100644 --- a/search/graphSearch.go +++ b/search/graphSearch.go @@ -140,8 +140,8 @@ func Dijkstra(source gr.Node, graph gr.Graph, cost gr.CostFun) (paths map[int][] // // Like Dijkstra's, along with the costs this implementation will also construct all the paths for you. In addition, it has a third return value which will be true if the algorithm was aborted // due to the presence of a negative edge weight cycle. -func BellmanFord(source gr.Node, graph gr.Graph, Cost func(gr.Node, gr.Node) float64) (paths map[int][]gr.Node, costs map[int]float64, err error) { - successors, _, _, _, _, _, Cost, _ := setupFuncs(graph, Cost, nil) +func BellmanFord(source gr.Node, graph gr.Graph, cost gr.CostFun) (paths map[int][]gr.Node, costs map[int]float64, err error) { + successors, _, _, _, _, _, cost, _ := setupFuncs(graph, cost, nil) predecessor := make(map[int]gr.Node) costs = make(map[int]float64) @@ -155,7 +155,7 @@ func BellmanFord(source gr.Node, graph gr.Graph, Cost func(gr.Node, gr.Node) flo nodeIDMap[node.ID()] = node succs := successors(node) for _, succ := range succs { - weight := Cost(node, succ) + weight := cost(node, succ) nodeIDMap[succ.ID()] = succ if dist := costs[node.ID()] + weight; dist < costs[succ.ID()] { @@ -169,7 +169,7 @@ func BellmanFord(source gr.Node, graph gr.Graph, Cost func(gr.Node, gr.Node) flo for _, node := range nodes { for _, succ := range successors(node) { - weight := Cost(node, succ) + weight := cost(node, succ) if costs[node.ID()]+weight < costs[succ.ID()] { return nil, nil, errors.New("Negative edge cycle detected") } From a5a71b11cf920d130e560f6293f0d01f65486186 Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:02:58 -0700 Subject: [PATCH 05/19] Updated Johnson --- search/graphSearch.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/search/graphSearch.go b/search/graphSearch.go index d7527d87..dadd3e74 100644 --- a/search/graphSearch.go +++ b/search/graphSearch.go @@ -195,8 +195,8 @@ func BellmanFord(source gr.Node, graph gr.Graph, cost gr.CostFun) (paths map[int // // Its return values are, in order: a map from the source node, to the destination node, to the path between them; a map from the source node, to the destination node, to the cost of the path between them; // and a bool that is true if Bellman-Ford detected a negative edge weight cycle -- thus causing it (and this algorithm) to abort (if aborted is true, both maps will be nil). -func Johnson(graph gr.Graph, Cost func(gr.Node, gr.Node) float64) (nodePaths map[int]map[int][]gr.Node, nodeCosts map[int]map[int]float64, err error) { - successors, _, _, _, _, _, Cost, _ := setupFuncs(graph, Cost, nil) +func Johnson(graph gr.Graph, cost gr.CostFun) (nodePaths map[int]map[int][]gr.Node, nodeCosts map[int]map[int]float64, err error) { + successors, _, _, _, _, _, cost, _ := setupFuncs(graph, cost, nil) /* Copy graph into a mutable one since it has to be altered for this algorithm */ dummyGraph := concrete.NewGonumGraph(true) for _, node := range graph.NodeList() { @@ -204,12 +204,12 @@ func Johnson(graph gr.Graph, Cost func(gr.Node, gr.Node) float64) (nodePaths map if !dummyGraph.NodeExists(node) { dummyGraph.AddNode(node, neighbors) for _, neighbor := range neighbors { - dummyGraph.SetEdgeCost(concrete.GonumEdge{node, neighbor}, Cost(node, neighbor)) + dummyGraph.SetEdgeCost(concrete.GonumEdge{node, neighbor}, cost(node, neighbor)) } } else { for _, neighbor := range neighbors { dummyGraph.AddEdge(concrete.GonumEdge{node, neighbor}) - dummyGraph.SetEdgeCost(concrete.GonumEdge{node, neighbor}, Cost(node, neighbor)) + dummyGraph.SetEdgeCost(concrete.GonumEdge{node, neighbor}, cost(node, neighbor)) } } } @@ -229,7 +229,7 @@ func Johnson(graph gr.Graph, Cost func(gr.Node, gr.Node) float64) (nodePaths map /* Step 3: reweight the graph and remove the dummy node */ for _, node := range graph.NodeList() { for _, succ := range successors(node) { - dummyGraph.SetEdgeCost(concrete.GonumEdge{node, succ}, Cost(node, succ)+costs[node.ID()]-costs[succ.ID()]) + dummyGraph.SetEdgeCost(concrete.GonumEdge{node, succ}, cost(node, succ)+costs[node.ID()]-costs[succ.ID()]) } } From 78e6bddeaa3ef3004a797a6a8fe38af5acec286b Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:04:30 -0700 Subject: [PATCH 06/19] Updated prim --- search/graphSearch.go | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/search/graphSearch.go b/search/graphSearch.go index dadd3e74..ac516d27 100644 --- a/search/graphSearch.go +++ b/search/graphSearch.go @@ -405,14 +405,8 @@ func IsPath(path []gr.Node, graph gr.Graph) bool { // Generates a minimum spanning tree with sets. // // As with other algorithms that use Cost, the order of precedence is Argument > Interface > UniformCost -func Prim(dst gr.MutableGraph, graph gr.EdgeListGraph, Cost func(gr.Node, gr.Node) float64) { - if Cost == nil { - if cgraph, ok := graph.(gr.Coster); ok { - Cost = cgraph.Cost - } else { - Cost = UniformCost - } - } +func Prim(dst gr.MutableGraph, graph gr.EdgeListGraph, cost gr.CostFun) { + _, _, _, _, _, _, cost, _ = setupFuncs(graph, cost, nil) dst.EmptyGraph() dst.SetDirected(false) @@ -433,9 +427,9 @@ func Prim(dst gr.MutableGraph, graph gr.EdgeListGraph, Cost func(gr.Node, gr.Nod edgeWeights := make(edgeSorter, 0) for _, edge := range edgeList { if dst.NodeExists(edge.Head()) && remainingNodes.Contains(edge.Tail().ID()) { - edgeWeights = append(edgeWeights, WeightedEdge{Edge: edge, Weight: Cost(edge.Head(), edge.Tail())}) + edgeWeights = append(edgeWeights, WeightedEdge{Edge: edge, Weight: cost(edge.Head(), edge.Tail())}) } else if dst.NodeExists(edge.Tail()) && remainingNodes.Contains(edge.Head().ID()) { - edgeWeights = append(edgeWeights, WeightedEdge{Edge: edge, Weight: Cost(edge.Tail(), edge.Head())}) + edgeWeights = append(edgeWeights, WeightedEdge{Edge: edge, Weight: cost(edge.Tail(), edge.Head())}) } } From c149619cfef7c83921b86315d4b8ab9911cff050 Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:10:48 -0700 Subject: [PATCH 07/19] Changed setupFuncs to use a struct --- search/internals.go | 50 +++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/search/internals.go b/search/internals.go index 9fd80126..73c255a0 100644 --- a/search/internals.go +++ b/search/internals.go @@ -6,51 +6,57 @@ import ( gr "github.com/gonum/graph" ) +type searchFuncs struct { + successors, predecessors, neighbors func(gr.Node) []gr.Node + isSuccessor, isPredecessor, isNeighbor func(gr.Node, gr.Node) bool + cost, heuristicCost gr.CostFun +} + // Sets up the cost functions and successor functions so I don't have to do a type switch every time. // This almost always does more work than is necessary, but since it's only executed once per function, and graph functions are rather costly, the "extra work" // should be negligible. -func setupFuncs(graph gr.Graph, cost, heuristicCost func(gr.Node, gr.Node) float64) (successorsFunc, predecessorsFunc, neighborsFunc func(gr.Node) []gr.Node, isSuccessorFunc, isPredecessorFunc, - isNeighborFunc func(gr.Node, gr.Node) bool, - costFunc, heuristicCostFunc func(gr.Node, gr.Node) float64) { +func setupFuncs(graph gr.Graph, cost, heuristicCost gr.CostFun) searchFuncs { + + sf := searchFuncs{} switch g := graph.(type) { case gr.DirectedGraph: - successorsFunc = g.Successors - predecessorsFunc = g.Predecessors - neighborsFunc = g.Neighbors - isSuccessorFunc = g.IsSuccessor - isPredecessorFunc = g.IsPredecessor - isNeighborFunc = g.IsNeighbor + sf.successors = g.Successors + sf.predecessors = g.Predecessors + sf.neighbors = g.Neighbors + sf.isSuccessor = g.IsSuccessor + sf.isPredecessor = g.IsPredecessor + sf.isNeighbor = g.IsNeighbor default: - successorsFunc = g.Neighbors - predecessorsFunc = g.Neighbors - neighborsFunc = g.Neighbors - isSuccessorFunc = g.IsNeighbor - isPredecessorFunc = g.IsNeighbor - isNeighborFunc = g.IsNeighbor + sf.successors = g.Neighbors + sf.predecessors = g.Neighbors + sf.neighbors = g.Neighbors + sf.isSuccessor = g.IsNeighbor + sf.isPredecessor = g.IsNeighbor + sf.isNeighbor = g.IsNeighbor } if heuristicCost != nil { - heuristicCostFunc = heuristicCost + sf.heuristicCost = heuristicCost } else { if g, ok := graph.(gr.HeuristicCoster); ok { - heuristicCostFunc = g.HeuristicCost + sf.heuristicCost = heuristicCost } else { - heuristicCostFunc = NullHeuristic + sf.heuristicCost = NullHeuristic } } if cost != nil { - costFunc = cost + sf.cost = cost } else { if g, ok := graph.(gr.Coster); ok { - costFunc = g.Cost + sf.cost = g.Cost } else { - costFunc = UniformCost + sf.cost = UniformCost } } - return + return sf } /* Purely internal data structures and functions (mostly for sorting) */ From 2b176ded929f180cbb63b3ab7ebe14559af2547b Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:11:36 -0700 Subject: [PATCH 08/19] Updated A* to use struct --- search/graphSearch.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/search/graphSearch.go b/search/graphSearch.go index ac516d27..596dff8b 100644 --- a/search/graphSearch.go +++ b/search/graphSearch.go @@ -31,7 +31,8 @@ import ( // // To run Breadth First Search, run A* with both the NullHeuristic and UniformCost (or any cost function that returns a uniform positive value) func AStar(start, goal gr.Node, graph gr.Graph, cost, heuristicCost gr.CostFun) (path []gr.Node, pathCost float64, nodesExpanded int) { - successors, _, _, _, _, _, cost, heuristicCost := setupFuncs(graph, cost, heuristicCost) + sf := setupFuncs(graph, cost, heuristicCost) + successors, cost, heuristicCost := sf.successors, sf.cost, sf.heuristicCost closedSet := make(map[int]internalNode) openSet := &aStarPriorityQueue{nodes: make([]internalNode, 0), indexList: make(map[int]int)} From f85b769181891526c92b3a9b368c419683152e61 Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:12:43 -0700 Subject: [PATCH 09/19] More struct updates --- search/graphSearch.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/search/graphSearch.go b/search/graphSearch.go index 596dff8b..6cadad04 100644 --- a/search/graphSearch.go +++ b/search/graphSearch.go @@ -91,7 +91,9 @@ func BreadthFirstSearch(start, goal gr.Node, graph gr.Graph) ([]gr.Node, int) { // // Dijkstra's algorithm usually only returns a cost map, however, since the data is available this version will also reconstruct the path to every node func Dijkstra(source gr.Node, graph gr.Graph, cost gr.CostFun) (paths map[int][]gr.Node, costs map[int]float64) { - successors, _, _, _, _, _, cost, _ := setupFuncs(graph, cost, nil) + + sf := setupFuncs(graph, cost, nil) + successors, cost := sf.successors, sf.cost nodes := graph.NodeList() openSet := &aStarPriorityQueue{nodes: make([]internalNode, 0), indexList: make(map[int]int)} @@ -142,7 +144,8 @@ func Dijkstra(source gr.Node, graph gr.Graph, cost gr.CostFun) (paths map[int][] // Like Dijkstra's, along with the costs this implementation will also construct all the paths for you. In addition, it has a third return value which will be true if the algorithm was aborted // due to the presence of a negative edge weight cycle. func BellmanFord(source gr.Node, graph gr.Graph, cost gr.CostFun) (paths map[int][]gr.Node, costs map[int]float64, err error) { - successors, _, _, _, _, _, cost, _ := setupFuncs(graph, cost, nil) + sf := setupFuncs(graph, cost, nil) + successors, cost := sf.successors, sf.cost predecessor := make(map[int]gr.Node) costs = make(map[int]float64) From c3159c86987932924530cbc2977d835718164f55 Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:13:36 -0700 Subject: [PATCH 10/19] Added struct change to Johnson --- search/graphSearch.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/search/graphSearch.go b/search/graphSearch.go index 6cadad04..88f2697c 100644 --- a/search/graphSearch.go +++ b/search/graphSearch.go @@ -200,7 +200,9 @@ func BellmanFord(source gr.Node, graph gr.Graph, cost gr.CostFun) (paths map[int // Its return values are, in order: a map from the source node, to the destination node, to the path between them; a map from the source node, to the destination node, to the cost of the path between them; // and a bool that is true if Bellman-Ford detected a negative edge weight cycle -- thus causing it (and this algorithm) to abort (if aborted is true, both maps will be nil). func Johnson(graph gr.Graph, cost gr.CostFun) (nodePaths map[int]map[int][]gr.Node, nodeCosts map[int]map[int]float64, err error) { - successors, _, _, _, _, _, cost, _ := setupFuncs(graph, cost, nil) + sf := setupFuncs(graph, cost, nil) + successors, cost := sf.successors, sf.cost + /* Copy graph into a mutable one since it has to be altered for this algorithm */ dummyGraph := concrete.NewGonumGraph(true) for _, node := range graph.NodeList() { From cbd99b374550f8a67485b86ad88f952437a8382f Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:14:08 -0700 Subject: [PATCH 11/19] Updated DFS for new struct --- search/graphSearch.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/search/graphSearch.go b/search/graphSearch.go index 88f2697c..a31f94c5 100644 --- a/search/graphSearch.go +++ b/search/graphSearch.go @@ -255,7 +255,9 @@ func Johnson(graph gr.Graph, cost gr.CostFun) (nodePaths map[int]map[int][]gr.No // 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 gr.Node, graph gr.Graph) []gr.Node { - successors, _, _, _, _, _, _, _ := setupFuncs(graph, nil, nil) + sf := setupFuncs(graph, nil, nil) + successors := sf.successors + closedSet := set.NewSet() openSet := xifo.GonumStack([]interface{}{start}) predecessor := make(map[int]gr.Node) From f7f6553bdefdf7700e208ddaf6396db56d2aed6c Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:14:45 -0700 Subject: [PATCH 12/19] Copy -> struct --- search/graphSearch.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/search/graphSearch.go b/search/graphSearch.go index a31f94c5..2d7f095c 100644 --- a/search/graphSearch.go +++ b/search/graphSearch.go @@ -307,7 +307,8 @@ func CopyGraph(dst gr.MutableGraph, src gr.Graph) { dst.EmptyGraph() dst.SetDirected(false) - successors, _, _, _, _, _, cost, _ := setupFuncs(src, nil, nil) + sf := setupFuncs(src, nil, nil) + successors, cost := sf.successors, sf.cost for _, node := range src.NodeList() { succs := successors(node) From c07e991fcb3c2ba45b488149c3f9fd6eac5fad27 Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:15:11 -0700 Subject: [PATCH 13/19] Targan -> struct --- search/graphSearch.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/search/graphSearch.go b/search/graphSearch.go index 2d7f095c..2f46208b 100644 --- a/search/graphSearch.go +++ b/search/graphSearch.go @@ -344,7 +344,7 @@ func Tarjan(graph gr.Graph) (sccs [][]gr.Node) { lowlinks := make(map[int]int, len(nodes)) indices := make(map[int]int, len(nodes)) - successors, _, _, _, _, _, _, _ := setupFuncs(graph, nil, nil) + successors := setupFuncs(graph, nil, nil).successors var strongconnect func(gr.Node) []gr.Node From 77ef5a1f3818e386ccb1a1b8cf3377a91f22d4f9 Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:15:40 -0700 Subject: [PATCH 14/19] IsPath -> struct --- search/graphSearch.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/search/graphSearch.go b/search/graphSearch.go index 2f46208b..cbaf06e2 100644 --- a/search/graphSearch.go +++ b/search/graphSearch.go @@ -393,7 +393,8 @@ func Tarjan(graph gr.Graph) (sccs [][]gr.Node) { // // Special case: a nil or zero length path is considered valid (true), a path of length 1 (only one node) is the trivial case, but only if the node listed in path exists. func IsPath(path []gr.Node, graph gr.Graph) bool { - _, _, _, isSuccessor, _, _, _, _ := setupFuncs(graph, nil, nil) + isSuccessor := setupFuncs(graph, nil, nil).isSuccessor + if path == nil || len(path) == 0 { return true } else if len(path) == 1 { From 2a4b1f77b6a3ab0587d531eb81de7b6d862521dc Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:15:59 -0700 Subject: [PATCH 15/19] Prim -> struct --- search/graphSearch.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/search/graphSearch.go b/search/graphSearch.go index cbaf06e2..21cbbb49 100644 --- a/search/graphSearch.go +++ b/search/graphSearch.go @@ -416,7 +416,8 @@ func IsPath(path []gr.Node, graph gr.Graph) bool { // // As with other algorithms that use Cost, the order of precedence is Argument > Interface > UniformCost func Prim(dst gr.MutableGraph, graph gr.EdgeListGraph, cost gr.CostFun) { - _, _, _, _, _, _, cost, _ = setupFuncs(graph, cost, nil) + cost = setupFuncs(graph, cost, nil).cost + dst.EmptyGraph() dst.SetDirected(false) From 7ed989ad9c7d1857b8e755bedca0974189235719 Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:16:14 -0700 Subject: [PATCH 16/19] Kruskal -> struct --- search/graphSearch.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/search/graphSearch.go b/search/graphSearch.go index 21cbbb49..c552f2d1 100644 --- a/search/graphSearch.go +++ b/search/graphSearch.go @@ -464,7 +464,8 @@ func Prim(dst gr.MutableGraph, graph gr.EdgeListGraph, cost gr.CostFun) { // // As with other algorithms with Cost, the precedence goes Argument > Interface > UniformCost func Kruskal(dst gr.MutableGraph, graph gr.EdgeListGraph, cost func(gr.Node, gr.Node) float64) { - _, _, _, _, _, _, cost, _ = setupFuncs(graph, cost, nil) + cost = setupFuncs(graph, cost, nil).cost + dst.EmptyGraph() dst.SetDirected(false) From f0f274553435200151a0105a122e7988d846e77b Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:16:36 -0700 Subject: [PATCH 17/19] Post-doms -> struct --- search/graphSearch.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/search/graphSearch.go b/search/graphSearch.go index c552f2d1..9749f849 100644 --- a/search/graphSearch.go +++ b/search/graphSearch.go @@ -512,7 +512,7 @@ func Dominators(start gr.Node, graph gr.Graph) map[int]*set.Set { allNodes.Add(node.ID()) } - _, predecessors, _, _, _, _, _, _ := setupFuncs(graph, nil, nil) + predecessors := setupFuncs(graph, nil, nil).predecessors for _, node := range nlist { dominators[node.ID()] = set.NewSet() From 96f03068cedcadd25b0c05f88616c1acfd01bba5 Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:16:51 -0700 Subject: [PATCH 18/19] Post-doms -> struct --- search/graphSearch.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/search/graphSearch.go b/search/graphSearch.go index 9749f849..03aa8ef1 100644 --- a/search/graphSearch.go +++ b/search/graphSearch.go @@ -556,7 +556,8 @@ func Dominators(start gr.Node, graph gr.Graph) map[int]*set.Set { // // This returns all possible post-dominators for all nodes, it does not prune for strict postdominators, immediate postdominators etc func PostDominators(end gr.Node, graph gr.Graph) map[int]*set.Set { - successors, _, _, _, _, _, _, _ := setupFuncs(graph, nil, nil) + successors := setupFuncs(graph, nil, nil).successors + allNodes := set.NewSet() nlist := graph.NodeList() dominators := make(map[int]*set.Set, len(nlist)) From 8d679ba473d1f168fc0060fc42be66333926716c Mon Sep 17 00:00:00 2001 From: Jsor Date: Thu, 6 Feb 2014 03:17:24 -0700 Subject: [PATCH 19/19] Finalized internals change --- search/internals.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/search/internals.go b/search/internals.go index 73c255a0..a14b8c3b 100644 --- a/search/internals.go +++ b/search/internals.go @@ -40,7 +40,7 @@ func setupFuncs(graph gr.Graph, cost, heuristicCost gr.CostFun) searchFuncs { sf.heuristicCost = heuristicCost } else { if g, ok := graph.(gr.HeuristicCoster); ok { - sf.heuristicCost = heuristicCost + sf.heuristicCost = g.HeuristicCost } else { sf.heuristicCost = NullHeuristic }