func (g *Graph) Traverse(privateState PrivateTraverseState, from, to *Node) (path []*Node, totalCost float64, ok bool) { seen := make(map[*Node]bool) state := &PublicTraverseState{0.0, from, &VisitedList{from, nil}, privateState} sh := sheap.NewSliceHeap(PublicStateLessThan) heap.Init(sh) heap.Push(sh, state) for !sh.IsEmpty() { state = heap.Pop(sh).(*PublicTraverseState) if _, found := seen[state.node]; found { continue } seen[state.node] = true if DEBUG&PROGRESSIVE_FLAG != 0 { fmt.Printf("%f : %s\n", state.totalCost, state.node.Record) } if state.node == to { return state.visited.MakeSlice(), state.totalCost, true } for _, vertex := range state.node.vertices { if DEBUG&TRAVERSE_FLAG != 0 { fmt.Printf("Considering %s to %s ... ", state.node.Record, vertex.To.Record) } totalCost := state.totalCost + vertex.Cost nextNode := vertex.To if state.visited.HasVisited(nextNode) { if DEBUG&TRAVERSE_FLAG != 0 { fmt.Println("already been there") } continue } nextPrivateState, ok := (state.privateState).TraverseStateHelper(vertex) if !ok { if DEBUG&TRAVERSE_FLAG != 0 { fmt.Println("rejected by calling code") } continue } nextPublicState := &PublicTraverseState{totalCost, nextNode, &VisitedList{nextNode, state.visited}, nextPrivateState} heap.Push(sh, nextPublicState) if DEBUG&TRAVERSE_FLAG != 0 { fmt.Printf("good w/ total cost of %f\n", totalCost) } } } return nil, 0.0, false }
func NewPriorityQueue(f func(a, b interface{}) bool) *PriorityQueue { sh := sheap.NewSliceHeap(f) heap.Init(sh) return &PriorityQueue{sh} }