github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/graph/path/bellman_ford_moore_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 path 6 7 import ( 8 "math" 9 "reflect" 10 "sort" 11 "testing" 12 13 "github.com/jingcheng-WU/gonum/graph" 14 "github.com/jingcheng-WU/gonum/graph/internal/ordered" 15 "github.com/jingcheng-WU/gonum/graph/path/internal/testgraphs" 16 "github.com/jingcheng-WU/gonum/graph/traverse" 17 ) 18 19 func TestBellmanFordFrom(t *testing.T) { 20 t.Parallel() 21 for _, test := range testgraphs.ShortestPathTests { 22 g := test.Graph() 23 for _, e := range test.Edges { 24 g.SetWeightedEdge(e) 25 } 26 27 for _, tg := range []struct { 28 typ string 29 g traverse.Graph 30 }{ 31 {"complete", g.(graph.Graph)}, 32 {"incremental", incremental{g.(graph.Weighted)}}, 33 } { 34 pt, ok := BellmanFordFrom(test.Query.From(), tg.g) 35 if test.HasNegativeCycle { 36 if ok { 37 t.Errorf("%q %s: expected negative cycle", test.Name, tg.typ) 38 } 39 } else if !ok { 40 t.Fatalf("%q %s: unexpected negative cycle", test.Name, tg.typ) 41 } 42 43 if pt.From().ID() != test.Query.From().ID() { 44 t.Fatalf("%q %s: unexpected from node ID: got:%d want:%d", test.Name, tg.typ, pt.From().ID(), test.Query.From().ID()) 45 } 46 47 p, weight := pt.To(test.Query.To().ID()) 48 if weight != test.Weight { 49 t.Errorf("%q %s: unexpected weight from To: got:%f want:%f", 50 test.Name, tg.typ, weight, test.Weight) 51 } 52 if weight := pt.WeightTo(test.Query.To().ID()); !math.IsInf(test.Weight, -1) && weight != test.Weight { 53 t.Errorf("%q %s: unexpected weight from Weight: got:%f want:%f", 54 test.Name, tg.typ, weight, test.Weight) 55 } 56 57 var got []int64 58 for _, n := range p { 59 got = append(got, n.ID()) 60 } 61 ok = len(got) == 0 && len(test.WantPaths) == 0 62 for _, sp := range test.WantPaths { 63 if reflect.DeepEqual(got, sp) { 64 ok = true 65 break 66 } 67 } 68 if !ok { 69 t.Errorf("%q %s: unexpected shortest path:\ngot: %v\nwant from:%v", 70 test.Name, tg.typ, p, test.WantPaths) 71 } 72 73 np, weight := pt.To(test.NoPathFor.To().ID()) 74 if pt.From().ID() == test.NoPathFor.From().ID() && (np != nil || !math.IsInf(weight, 1)) { 75 t.Errorf("%q %s: unexpected path:\ngot: path=%v weight=%f\nwant:path=<nil> weight=+Inf", 76 test.Name, tg.typ, np, weight) 77 } 78 } 79 } 80 } 81 82 func TestBellmanFordAllFrom(t *testing.T) { 83 t.Parallel() 84 for _, test := range testgraphs.ShortestPathTests { 85 g := test.Graph() 86 for _, e := range test.Edges { 87 g.SetWeightedEdge(e) 88 } 89 90 for _, tg := range []struct { 91 typ string 92 g traverse.Graph 93 }{ 94 {"complete", g.(graph.Graph)}, 95 {"incremental", incremental{g.(graph.Weighted)}}, 96 } { 97 pt, ok := BellmanFordAllFrom(test.Query.From(), tg.g) 98 if test.HasNegativeCycle { 99 if ok { 100 t.Errorf("%q %s: expected negative cycle", test.Name, tg.typ) 101 } 102 } else if !ok { 103 t.Fatalf("%q %s: unexpected negative cycle", test.Name, tg.typ) 104 } 105 106 if pt.From().ID() != test.Query.From().ID() { 107 t.Fatalf("%q %s: unexpected from node ID: got:%d want:%d", test.Name, tg.typ, pt.From().ID(), test.Query.From().ID()) 108 } 109 110 // Test single path results. 111 p, weight, unique := pt.To(test.Query.To().ID()) 112 if weight != test.Weight { 113 t.Errorf("%q %s: unexpected weight from To: got:%f want:%f", 114 test.Name, tg.typ, weight, test.Weight) 115 } 116 if weight := pt.WeightTo(test.Query.To().ID()); !math.IsInf(test.Weight, -1) && weight != test.Weight { 117 t.Errorf("%q %s: unexpected weight from Weight: got:%f want:%f", 118 test.Name, tg.typ, weight, test.Weight) 119 } 120 121 var gotPath []int64 122 for _, n := range p { 123 gotPath = append(gotPath, n.ID()) 124 } 125 ok = len(gotPath) == 0 && len(test.WantPaths) == 0 126 for _, sp := range test.WantPaths { 127 if reflect.DeepEqual(gotPath, sp) { 128 ok = true 129 break 130 } 131 } 132 if !ok { 133 t.Errorf("%q %s: unexpected shortest path:\ngot: %v\nwant from:%v", 134 test.Name, tg.typ, p, test.WantPaths) 135 } 136 if unique != test.HasUniquePath { 137 t.Errorf("%q %s: unexpected uniqueness from To: got:%t want:%t (%d paths)", 138 test.Name, tg.typ, unique, test.HasUniquePath, len(test.WantPaths)) 139 } 140 141 // Test multiple path results. 142 paths, weight := pt.AllTo(test.Query.To().ID()) 143 if weight != test.Weight { 144 t.Errorf("%q %s: unexpected weight from AllTo: got:%f want:%f", 145 test.Name, tg.typ, weight, test.Weight) 146 } 147 if weight := pt.WeightTo(test.Query.To().ID()); !math.IsInf(test.Weight, -1) && weight != test.Weight { 148 t.Errorf("%q %s: unexpected weight from Weight: got:%f want:%f", 149 test.Name, tg.typ, weight, test.Weight) 150 } 151 152 var gotPaths [][]int64 153 if len(paths) != 0 { 154 gotPaths = make([][]int64, len(paths)) 155 } 156 for i, p := range paths { 157 for _, v := range p { 158 gotPaths[i] = append(gotPaths[i], v.ID()) 159 } 160 } 161 if test.HasNegativeCycleInPath { 162 if gotPaths != nil { 163 t.Errorf("testing %q %s: unexpected shortest paths:\ngot: %v\nwant: []", 164 test.Name, tg.typ, gotPaths) 165 } 166 } else { 167 sort.Sort(ordered.BySliceValues(gotPaths)) 168 if !reflect.DeepEqual(gotPaths, test.WantPaths) { 169 t.Errorf("testing %q %s: unexpected shortest paths:\ngot: %v\nwant:%v", 170 test.Name, tg.typ, gotPaths, test.WantPaths) 171 } 172 } 173 174 // Test absent paths. 175 np, weight, unique := pt.To(test.NoPathFor.To().ID()) 176 if pt.From().ID() == test.NoPathFor.From().ID() && !(np == nil && math.IsInf(weight, 1) && !unique) { 177 t.Errorf("%q %s: unexpected path:\ngot: path=%v weight=%f unique=%t\nwant:path=<nil> weight=+Inf unique=false", 178 test.Name, tg.typ, np, weight, unique) 179 } 180 } 181 } 182 }