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  }