mirror of
https://github.com/gonum/gonum.git
synced 2025-10-07 16:11:03 +08:00
graph: move NewEdge method from encoding.Builder to graph.EdgeAdder
Also rename graph.EdgeSetter to graph.EdgeAdder. Fixes #56.
This commit is contained in:
@@ -167,21 +167,23 @@ func (gen *generator) addStmt(dst encoding.Builder, stmt ast.Stmt) {
|
||||
}
|
||||
|
||||
// addEdgeStmt adds the given edge statement to the graph.
|
||||
func (gen *generator) addEdgeStmt(dst encoding.Builder, e *ast.EdgeStmt) {
|
||||
fs := gen.addVertex(dst, e.From)
|
||||
ts := gen.addEdge(dst, e.To)
|
||||
func (gen *generator) addEdgeStmt(dst encoding.Builder, stmt *ast.EdgeStmt) {
|
||||
fs := gen.addVertex(dst, stmt.From)
|
||||
ts := gen.addEdge(dst, stmt.To)
|
||||
for _, f := range fs {
|
||||
for _, t := range ts {
|
||||
edge, ok := dst.NewEdge(f, t).(encoding.AttributeSetter)
|
||||
edge := dst.NewEdge(f, t)
|
||||
dst.SetEdge(edge)
|
||||
e, ok := edge.(encoding.AttributeSetter)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for _, attr := range e.Attrs {
|
||||
for _, attr := range stmt.Attrs {
|
||||
a := encoding.Attribute{
|
||||
Key: attr.Key,
|
||||
Value: attr.Val,
|
||||
}
|
||||
if err := edge.SetAttribute(a); err != nil {
|
||||
if err := e.SetAttribute(a); err != nil {
|
||||
panic(fmt.Errorf("unable to unmarshal edge DOT attribute (%s=%s)", a.Key, a.Value))
|
||||
}
|
||||
}
|
||||
@@ -216,7 +218,8 @@ func (gen *generator) addEdge(dst encoding.Builder, to *ast.Edge) []graph.Node {
|
||||
ts := gen.addEdge(dst, to.To)
|
||||
for _, f := range fs {
|
||||
for _, t := range ts {
|
||||
dst.NewEdge(f, t)
|
||||
edge := dst.NewEdge(f, t)
|
||||
dst.SetEdge(edge)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -118,15 +118,9 @@ func (g *dotDirectedGraph) NewNode() graph.Node {
|
||||
return &dotNode{Node: g.DirectedGraph.NewNode()}
|
||||
}
|
||||
|
||||
// NewEdge adds a new edge from the source to the destination node to the graph,
|
||||
// or returns the existing edge if already present.
|
||||
// NewEdge returns a new Edge from the source to the destination node.
|
||||
func (g *dotDirectedGraph) NewEdge(from, to graph.Node) graph.Edge {
|
||||
if e := g.Edge(from, to); e != nil {
|
||||
return e
|
||||
}
|
||||
e := &dotEdge{Edge: simple.Edge{F: from, T: to}}
|
||||
g.SetEdge(e)
|
||||
return e
|
||||
return &dotEdge{Edge: g.DirectedGraph.NewEdge(from, to)}
|
||||
}
|
||||
|
||||
// DOTAttributers implements the dot.Attributers interface.
|
||||
@@ -159,15 +153,9 @@ func (g *dotUndirectedGraph) NewNode() graph.Node {
|
||||
return &dotNode{Node: g.UndirectedGraph.NewNode()}
|
||||
}
|
||||
|
||||
// NewEdge adds a new edge from the source to the destination node to the graph,
|
||||
// or returns the existing edge if already present.
|
||||
// NewEdge returns a new Edge from the source to the destination node.
|
||||
func (g *dotUndirectedGraph) NewEdge(from, to graph.Node) graph.Edge {
|
||||
if e := g.Edge(from, to); e != nil {
|
||||
return e
|
||||
}
|
||||
e := &dotEdge{Edge: simple.Edge{F: from, T: to}}
|
||||
g.SetEdge(e)
|
||||
return e
|
||||
return &dotEdge{Edge: g.UndirectedGraph.NewEdge(from, to)}
|
||||
}
|
||||
|
||||
// DOTAttributers implements the dot.Attributers interface.
|
||||
@@ -222,7 +210,7 @@ func (n *dotNode) Attributes() []encoding.Attribute {
|
||||
// dotEdge extends simple.Edge with a label field to test round-trip encoding and
|
||||
// decoding of edge DOT label attributes.
|
||||
type dotEdge struct {
|
||||
simple.Edge
|
||||
graph.Edge
|
||||
// Edge label.
|
||||
Label string
|
||||
}
|
||||
|
@@ -11,9 +11,6 @@ import "gonum.org/v1/gonum/graph"
|
||||
type Builder interface {
|
||||
graph.Graph
|
||||
graph.Builder
|
||||
// NewEdge adds a new edge from the source to the destination node to the
|
||||
// graph, or returns the existing edge if already present.
|
||||
NewEdge(from, to graph.Node) graph.Edge
|
||||
}
|
||||
|
||||
// AttributeSetter is implemented by types that can set an encoded graph
|
||||
|
@@ -163,12 +163,7 @@ func (g *directedGraph) NewNode() graph.Node {
|
||||
}
|
||||
|
||||
func (g *directedGraph) NewEdge(from, to graph.Node) graph.Edge {
|
||||
if e := g.Edge(from, to); e != nil {
|
||||
return e
|
||||
}
|
||||
e := &edge{Edge: simple.Edge{F: from, T: to}}
|
||||
g.SetEdge(e)
|
||||
return e
|
||||
return &edge{Edge: g.DirectedGraph.NewEdge(from, to)}
|
||||
}
|
||||
|
||||
type node struct {
|
||||
@@ -189,7 +184,7 @@ func (n *node) SetIDFromString(uid string) error {
|
||||
}
|
||||
|
||||
type edge struct {
|
||||
simple.Edge
|
||||
graph.Edge
|
||||
label string
|
||||
}
|
||||
|
||||
|
@@ -93,13 +93,16 @@ type NodeRemover interface {
|
||||
RemoveNode(Node)
|
||||
}
|
||||
|
||||
// EdgeSetter is an interface for adding edges to a graph.
|
||||
type EdgeSetter interface {
|
||||
// EdgeAdder is an interface for adding edges to a graph.
|
||||
type EdgeAdder interface {
|
||||
// NewEdge returns a new Edge from the source to the destination node.
|
||||
NewEdge(from, to Node) Edge
|
||||
|
||||
// SetEdge adds an edge from one node to another.
|
||||
// If the graph supports node addition the nodes
|
||||
// will be added if they do not exist, otherwise
|
||||
// SetEdge will panic.
|
||||
// The behavior of an EdgeSetter when the IDs
|
||||
// The behavior of an EdgeAdder when the IDs
|
||||
// returned by e.From and e.To are equal is
|
||||
// implementation-dependent.
|
||||
SetEdge(e Edge)
|
||||
@@ -116,7 +119,7 @@ type EdgeRemover interface {
|
||||
// Builder is a graph that can have nodes and edges added.
|
||||
type Builder interface {
|
||||
NodeAdder
|
||||
EdgeSetter
|
||||
EdgeAdder
|
||||
}
|
||||
|
||||
// UndirectedBuilder is an undirected graph builder.
|
||||
|
@@ -25,7 +25,7 @@ func init() {
|
||||
// dynamic shortest path routine in path/dynamic: DStarLite.
|
||||
var ShortestPathTests = []struct {
|
||||
Name string
|
||||
Graph func() graph.EdgeSetter
|
||||
Graph func() graph.EdgeAdder
|
||||
Edges []simple.Edge
|
||||
HasNegativeWeight bool
|
||||
HasNegativeCycle bool
|
||||
@@ -40,7 +40,7 @@ var ShortestPathTests = []struct {
|
||||
// Positive weighted graphs.
|
||||
{
|
||||
Name: "empty directed",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
|
||||
Query: simple.Edge{F: simple.Node(0), T: simple.Node(1)},
|
||||
Weight: math.Inf(1),
|
||||
@@ -49,7 +49,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "empty undirected",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewUndirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewUndirectedGraph(0, math.Inf(1)) },
|
||||
|
||||
Query: simple.Edge{F: simple.Node(0), T: simple.Node(1)},
|
||||
Weight: math.Inf(1),
|
||||
@@ -58,7 +58,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "one edge directed",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
{F: simple.Node(0), T: simple.Node(1), W: 1},
|
||||
},
|
||||
@@ -74,7 +74,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "one edge self directed",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
{F: simple.Node(0), T: simple.Node(1), W: 1},
|
||||
},
|
||||
@@ -90,7 +90,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "one edge undirected",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewUndirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewUndirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
{F: simple.Node(0), T: simple.Node(1), W: 1},
|
||||
},
|
||||
@@ -106,7 +106,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "two paths directed",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
{F: simple.Node(0), T: simple.Node(2), W: 2},
|
||||
{F: simple.Node(0), T: simple.Node(1), W: 1},
|
||||
@@ -125,7 +125,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "two paths undirected",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewUndirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewUndirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
{F: simple.Node(0), T: simple.Node(2), W: 2},
|
||||
{F: simple.Node(0), T: simple.Node(1), W: 1},
|
||||
@@ -144,7 +144,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "confounding paths directed",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
// Add a path from 0->5 of weight 4
|
||||
{F: simple.Node(0), T: simple.Node(1), W: 1},
|
||||
@@ -178,7 +178,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "confounding paths undirected",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewUndirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewUndirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
// Add a path from 0->5 of weight 4
|
||||
{F: simple.Node(0), T: simple.Node(1), W: 1},
|
||||
@@ -212,7 +212,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "confounding paths directed 2-step",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
// Add a path from 0->5 of weight 4
|
||||
{F: simple.Node(0), T: simple.Node(1), W: 1},
|
||||
@@ -247,7 +247,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "confounding paths undirected 2-step",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewUndirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewUndirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
// Add a path from 0->5 of weight 4
|
||||
{F: simple.Node(0), T: simple.Node(1), W: 1},
|
||||
@@ -282,7 +282,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "zero-weight cycle directed",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
// Add a path from 0->4 of weight 4
|
||||
{F: simple.Node(0), T: simple.Node(1), W: 1},
|
||||
@@ -306,7 +306,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "zero-weight cycle^2 directed",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
// Add a path from 0->4 of weight 4
|
||||
{F: simple.Node(0), T: simple.Node(1), W: 1},
|
||||
@@ -333,7 +333,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "zero-weight cycle^2 confounding directed",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
// Add a path from 0->4 of weight 4
|
||||
{F: simple.Node(0), T: simple.Node(1), W: 1},
|
||||
@@ -363,7 +363,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "zero-weight cycle^3 directed",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
// Add a path from 0->4 of weight 4
|
||||
{F: simple.Node(0), T: simple.Node(1), W: 1},
|
||||
@@ -393,7 +393,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "zero-weight 3·cycle^2 confounding directed",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
// Add a path from 0->4 of weight 4
|
||||
{F: simple.Node(0), T: simple.Node(1), W: 1},
|
||||
@@ -429,7 +429,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "zero-weight reversed 3·cycle^2 confounding directed",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
// Add a path from 0->4 of weight 4
|
||||
{F: simple.Node(0), T: simple.Node(1), W: 1},
|
||||
@@ -465,7 +465,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "zero-weight |V|·cycle^(n/|V|) directed",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Edges: func() []simple.Edge {
|
||||
e := []simple.Edge{
|
||||
// Add a path from 0->4 of weight 4
|
||||
@@ -498,7 +498,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "zero-weight n·cycle directed",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Edges: func() []simple.Edge {
|
||||
e := []simple.Edge{
|
||||
// Add a path from 0->4 of weight 4
|
||||
@@ -531,7 +531,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "zero-weight bi-directional tree with single exit directed",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Edges: func() []simple.Edge {
|
||||
e := []simple.Edge{
|
||||
// Add a path from 0->4 of weight 4
|
||||
@@ -579,7 +579,7 @@ var ShortestPathTests = []struct {
|
||||
// Negative weighted graphs.
|
||||
{
|
||||
Name: "one edge directed negative",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
{F: simple.Node(0), T: simple.Node(1), W: -1},
|
||||
},
|
||||
@@ -596,7 +596,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "one edge undirected negative",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewUndirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewUndirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
{F: simple.Node(0), T: simple.Node(1), W: -1},
|
||||
},
|
||||
@@ -607,7 +607,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "wp graph negative", // http://en.wikipedia.org/w/index.php?title=Johnson%27s_algorithm&oldid=564595231
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
{F: simple.Node('w'), T: simple.Node('z'), W: 2},
|
||||
{F: simple.Node('x'), T: simple.Node('w'), W: 6},
|
||||
@@ -630,7 +630,7 @@ var ShortestPathTests = []struct {
|
||||
},
|
||||
{
|
||||
Name: "roughgarden negative",
|
||||
Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Graph: func() graph.EdgeAdder { return simple.NewDirectedGraph(0, math.Inf(1)) },
|
||||
Edges: []simple.Edge{
|
||||
{F: simple.Node('a'), T: simple.Node('b'), W: -2},
|
||||
{F: simple.Node('b'), T: simple.Node('c'), W: -1},
|
||||
|
@@ -80,6 +80,11 @@ func (g *DirectedGraph) RemoveNode(n graph.Node) {
|
||||
g.nodeIDs.release(n.ID())
|
||||
}
|
||||
|
||||
// NewEdge returns a new Edge from the source to the destination node.
|
||||
func (g *DirectedGraph) NewEdge(from, to graph.Node) graph.Edge {
|
||||
return &Edge{F: from, T: to}
|
||||
}
|
||||
|
||||
// SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added.
|
||||
// It will panic if the IDs of the e.From and e.To are equal.
|
||||
func (g *DirectedGraph) SetEdge(e graph.Edge) {
|
||||
|
@@ -72,6 +72,11 @@ func (g *UndirectedGraph) RemoveNode(n graph.Node) {
|
||||
g.nodeIDs.release(n.ID())
|
||||
}
|
||||
|
||||
// NewEdge returns a new Edge from the source to the destination node.
|
||||
func (g *UndirectedGraph) NewEdge(from, to graph.Node) graph.Edge {
|
||||
return &Edge{F: from, T: to}
|
||||
}
|
||||
|
||||
// SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added.
|
||||
// It will panic if the IDs of the e.From and e.To are equal.
|
||||
func (g *UndirectedGraph) SetEdge(e graph.Edge) {
|
||||
|
Reference in New Issue
Block a user