graph/multi: use more efficient and correct direction dedup logic
Also add test case to testgraph corpus.
diff --git a/graph/multi/undirected.go b/graph/multi/undirected.go
index c6bd747..d28c309 100644
--- a/graph/multi/undirected.go
+++ b/graph/multi/undirected.go
@@ -77,25 +77,27 @@
return graph.Empty
}
var edges []graph.Edge
- seen := make(map[int64]struct{})
- for _, u := range g.lines {
- for _, e := range u {
- var lines []graph.Line
+ for xid, u := range g.lines {
+ for yid, e := range u {
+ if yid < xid {
+ // Do not consider lines when the To node ID is
+ // before the From node ID. Both orientations
+ // are stored.
+ continue
+ }
+ // TODO(kortschak): Add iterator.Lines and use that here.
+ if len(e) == 0 {
+ continue
+ }
+ lines := make([]graph.Line, 0, len(e))
for _, l := range e {
- lid := l.ID()
- if _, ok := seen[lid]; ok {
- continue
- }
- seen[lid] = struct{}{}
lines = append(lines, l)
}
- if len(lines) != 0 {
- edges = append(edges, Edge{
- F: g.Node(lines[0].From().ID()),
- T: g.Node(lines[0].To().ID()),
- Lines: iterator.NewOrderedLines(lines),
- })
- }
+ edges = append(edges, Edge{
+ F: g.Node(xid),
+ T: g.Node(yid),
+ Lines: iterator.NewOrderedLines(lines),
+ })
}
}
if len(edges) == 0 {
diff --git a/graph/multi/weighted_undirected.go b/graph/multi/weighted_undirected.go
index a2a2944..d8ed075 100644
--- a/graph/multi/weighted_undirected.go
+++ b/graph/multi/weighted_undirected.go
@@ -82,26 +82,28 @@
return graph.Empty
}
var edges []graph.Edge
- seen := make(map[int64]struct{})
- for _, u := range g.lines {
- for _, e := range u {
- var lines []graph.WeightedLine
+ for xid, u := range g.lines {
+ for yid, e := range u {
+ if yid < xid {
+ // Do not consider lines when the To node ID is
+ // before the From node ID. Both orientations
+ // are stored.
+ continue
+ }
+ // TODO(kortschak): Add iterator.WeightedLines and use that here.
+ if len(e) == 0 {
+ continue
+ }
+ lines := make([]graph.WeightedLine, 0, len(e))
for _, l := range e {
- lid := l.ID()
- if _, ok := seen[lid]; ok {
- continue
- }
- seen[lid] = struct{}{}
lines = append(lines, l)
}
- if len(lines) != 0 {
- edges = append(edges, WeightedEdge{
- F: g.Node(lines[0].From().ID()),
- T: g.Node(lines[0].To().ID()),
- WeightedLines: iterator.NewOrderedWeightedLines(lines),
- WeightFunc: g.EdgeWeightFunc,
- })
- }
+ edges = append(edges, WeightedEdge{
+ F: g.Node(xid),
+ T: g.Node(yid),
+ WeightedLines: iterator.NewOrderedWeightedLines(lines),
+ WeightFunc: g.EdgeWeightFunc,
+ })
}
}
if len(edges) == 0 {
@@ -334,26 +336,28 @@
return graph.Empty
}
var edges []graph.WeightedEdge
- seen := make(map[int64]struct{})
- for _, u := range g.lines {
- for _, e := range u {
- var lines []graph.WeightedLine
+ for xid, u := range g.lines {
+ for yid, e := range u {
+ if yid < xid {
+ // Do not consider lines when the To node ID is
+ // before the From node ID. Both orientations
+ // are stored.
+ continue
+ }
+ // TODO(kortschak): Add iterator.WeightedLines and use that here.
+ if len(e) == 0 {
+ continue
+ }
+ lines := make([]graph.WeightedLine, 0, len(e))
for _, l := range e {
- lid := l.ID()
- if _, ok := seen[lid]; ok {
- continue
- }
- seen[lid] = struct{}{}
lines = append(lines, l)
}
- if len(lines) != 0 {
- edges = append(edges, WeightedEdge{
- F: g.Node(lines[0].From().ID()),
- T: g.Node(lines[0].To().ID()),
- WeightedLines: iterator.NewOrderedWeightedLines(lines),
- WeightFunc: g.EdgeWeightFunc,
- })
- }
+ edges = append(edges, WeightedEdge{
+ F: g.Node(xid),
+ T: g.Node(yid),
+ WeightedLines: iterator.NewOrderedWeightedLines(lines),
+ WeightFunc: g.EdgeWeightFunc,
+ })
}
}
if len(edges) == 0 {
diff --git a/graph/testgraph/testcases.go b/graph/testgraph/testcases.go
index 347e8a7..fb9a971 100644
--- a/graph/testgraph/testcases.go
+++ b/graph/testgraph/testcases.go
@@ -369,4 +369,15 @@
self: 0,
absent: math.Inf(1),
},
+ {
+ name: "issue 1686",
+ nodes: []graph.Node{node(0), node(1), node(2)},
+ edges: []WeightedLine{
+ line{F: node(0), T: node(1), UID: 0, W: 0.5},
+ line{F: node(1), T: node(2), UID: 0, W: 0.5},
+ },
+ nonexist: []graph.Node{node(-1), node(4)},
+ self: 0,
+ absent: math.Inf(1),
+ },
}