github.com/gopherd/gonum@v0.0.4/graph/path/dynamic/dumper_test.go (about) 1 // Copyright ©2015 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package dynamic 6 7 import ( 8 "bytes" 9 "fmt" 10 "io" 11 "sort" 12 "text/tabwriter" 13 14 "github.com/gopherd/gonum/graph/path/internal/testgraphs" 15 "github.com/gopherd/gonum/graph/simple" 16 ) 17 18 // dumper implements a grid D* Lite statistics dump. 19 type dumper struct { 20 step int 21 22 dStarLite *DStarLite 23 grid *testgraphs.LimitedVisionGrid 24 25 w io.Writer 26 } 27 28 // dump writes a single step of a D* Lite path search to the dumper's io.Writer. 29 func (d *dumper) dump(withpath bool) { 30 if d == nil { 31 return 32 } 33 var pathStep map[int64]int 34 if withpath { 35 pathStep = make(map[int64]int) 36 path, _ := d.dStarLite.Path() 37 for i, n := range path { 38 pathStep[n.ID()] = i 39 } 40 } 41 fmt.Fprintf(d.w, "Step:%d kₘ=%v\n", d.step, d.dStarLite.keyModifier) 42 d.step++ 43 w := tabwriter.NewWriter(d.w, 0, 0, 0, ' ', tabwriter.Debug) 44 rows, cols := d.grid.Grid.Dims() 45 for r := 0; r < rows; r++ { 46 if r == 0 { 47 for c := 0; c < cols; c++ { 48 if c != 0 { 49 fmt.Fprint(w, "\t") 50 } 51 fmt.Fprint(w, "-------------------") 52 } 53 fmt.Fprintln(w) 54 } 55 for ln := 0; ln < 6; ln++ { 56 for c := 0; c < cols; c++ { 57 if c != 0 { 58 fmt.Fprint(w, "\t") 59 } 60 n := d.dStarLite.model.Node(d.grid.NodeAt(r, c).ID()).(*dStarLiteNode) 61 switch ln { 62 case 0: 63 if n.ID() == d.grid.Location.ID() { 64 if d.grid.Grid.HasOpen(n.ID()) { 65 fmt.Fprintf(w, "id:%2d >@<", n.ID()) 66 } else { 67 // Mark location as illegal. 68 fmt.Fprintf(w, "id:%2d >!<", n.ID()) 69 } 70 } else if n.ID() == d.dStarLite.t.ID() { 71 fmt.Fprintf(w, "id:%2d G", n.ID()) 72 // Mark goal cell as illegal. 73 if !d.grid.Grid.HasOpen(n.ID()) { 74 fmt.Fprint(w, "!") 75 } 76 } else if pathStep[n.ID()] > 0 { 77 fmt.Fprintf(w, "id:%2d %2d", n.ID(), pathStep[n.ID()]) 78 // Mark path cells with an obstruction. 79 if !d.grid.Grid.HasOpen(n.ID()) { 80 fmt.Fprint(w, "!") 81 } 82 } else { 83 fmt.Fprintf(w, "id:%2d", n.ID()) 84 // Mark cells with an obstruction. 85 if !d.grid.Grid.HasOpen(n.ID()) { 86 fmt.Fprint(w, " *") 87 } 88 } 89 case 1: 90 fmt.Fprintf(w, "h: %.4v", d.dStarLite.heuristic(n, d.dStarLite.Here())) 91 case 2: 92 fmt.Fprintf(w, "g: %.4v", n.g) 93 case 3: 94 fmt.Fprintf(w, "rhs:%.4v", n.rhs) 95 case 4: 96 if n.g != n.rhs { 97 fmt.Fprintf(w, "key:%.3f", n.key) 98 } 99 if !n.key.isBadKey() { 100 // Mark keys for nodes in the priority queue. 101 // We use NaN inequality for this check since all 102 // keys not in the queue must have their key set 103 // to badKey. 104 // 105 // This should always mark cells where key is 106 // printed. 107 fmt.Fprint(w, "*") 108 } 109 if n.g > n.rhs { 110 fmt.Fprint(w, "^") 111 } 112 if n.g < n.rhs { 113 fmt.Fprint(w, "v") 114 } 115 default: 116 fmt.Fprint(w, "-------------------") 117 } 118 } 119 fmt.Fprintln(w) 120 } 121 } 122 w.Flush() 123 fmt.Fprintln(d.w) 124 } 125 126 // printEdges pretty prints the given edges to the dumper's io.Writer using the provided 127 // format string. The edges are first formated to a string, so the format string must use 128 // the %s verb to indicate where the edges are to be printed. 129 func (d *dumper) printEdges(format string, edges []simple.WeightedEdge) { 130 if d == nil { 131 return 132 } 133 var buf bytes.Buffer 134 sort.Sort(lexically(edges)) 135 for i, e := range edges { 136 if i != 0 { 137 fmt.Fprint(&buf, ", ") 138 } 139 fmt.Fprintf(&buf, "%d->%d:%.4v", e.From().ID(), e.To().ID(), e.Weight()) 140 } 141 if len(edges) == 0 { 142 fmt.Fprint(&buf, "none") 143 } 144 fmt.Fprintf(d.w, format, buf.Bytes()) 145 } 146 147 type lexically []simple.WeightedEdge 148 149 func (l lexically) Len() int { return len(l) } 150 func (l lexically) Less(i, j int) bool { 151 return l[i].From().ID() < l[j].From().ID() || (l[i].From().ID() == l[j].From().ID() && l[i].To().ID() < l[j].To().ID()) 152 } 153 func (l lexically) Swap(i, j int) { l[i], l[j] = l[j], l[i] }