mirror of
https://github.com/gonum/gonum.git
synced 2025-10-06 15:47:01 +08:00
graph/path: do not keep duplicate paths in YenKShortestPaths
Previously the code did not ignore spur paths that had already been added into the list of potential paths. This could cause the search to return duplicate paths for certain graphs.
This commit is contained in:
@@ -85,7 +85,18 @@ func YenKShortestPaths(g graph.Graph, k int, cost float64, s, t graph.Node) [][]
|
||||
spath = append(root[:len(root)-1], spath...)
|
||||
weight += rootWeight
|
||||
}
|
||||
pot = append(pot, yenShortest{spath, weight})
|
||||
|
||||
// Add the potential k-shortest path if it is new.
|
||||
isNewPot := true
|
||||
for x := range pot {
|
||||
if isSamePath(pot[x].path, spath) {
|
||||
isNewPot = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if isNewPot {
|
||||
pot = append(pot, yenShortest{spath, weight})
|
||||
}
|
||||
}
|
||||
|
||||
if len(pot) == 0 {
|
||||
@@ -104,6 +115,19 @@ func YenKShortestPaths(g graph.Graph, k int, cost float64, s, t graph.Node) [][]
|
||||
return paths
|
||||
}
|
||||
|
||||
func isSamePath(a, b []graph.Node) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, x := range a {
|
||||
if x.ID() != b[i].ID() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// yenShortest holds a path and its weight for sorting.
|
||||
type yenShortest struct {
|
||||
path []graph.Node
|
||||
|
@@ -306,6 +306,28 @@ var yenShortestPathTests = []struct {
|
||||
{8, 2, 4, 3, 7, 5},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "grid", // This is the failing case in gonum/gonum#1920.
|
||||
graph: func() graph.WeightedEdgeAdder { return simple.NewWeightedUndirectedGraph(0, math.Inf(1)) },
|
||||
edges: []simple.WeightedEdge{
|
||||
{F: simple.Node(1), T: simple.Node(2), W: 1},
|
||||
{F: simple.Node(2), T: simple.Node(3), W: 2},
|
||||
{F: simple.Node(3), T: simple.Node(6), W: 5},
|
||||
{F: simple.Node(1), T: simple.Node(4), W: 5},
|
||||
{F: simple.Node(2), T: simple.Node(5), W: 4},
|
||||
{F: simple.Node(4), T: simple.Node(5), W: 6},
|
||||
{F: simple.Node(5), T: simple.Node(6), W: 7},
|
||||
},
|
||||
query: simple.Edge{F: simple.Node(1), T: simple.Node(6)},
|
||||
k: -1,
|
||||
cost: math.Inf(1),
|
||||
wantPaths: [][]int64{
|
||||
{1, 2, 3, 6},
|
||||
{1, 2, 5, 6},
|
||||
{1, 4, 5, 6},
|
||||
{1, 4, 5, 2, 3, 6},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func bipartite(n int, weight, inc float64) []simple.WeightedEdge {
|
||||
|
Reference in New Issue
Block a user