github.com/gopherd/gonum@v0.0.4/graph/graph.go (about)

     1  // Copyright ©2014 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 graph
     6  
     7  // Node is a graph node. It returns a graph-unique integer ID.
     8  type Node interface {
     9  	ID() int64
    10  }
    11  
    12  // Edge is a graph edge. In directed graphs, the direction of the
    13  // edge is given from -> to, otherwise the edge is semantically
    14  // unordered.
    15  type Edge interface {
    16  	// From returns the from node of the edge.
    17  	From() Node
    18  
    19  	// To returns the to node of the edge.
    20  	To() Node
    21  
    22  	// ReversedEdge returns the edge reversal of the receiver
    23  	// if a reversal is valid for the data type.
    24  	// When a reversal is valid an edge of the same type as
    25  	// the receiver with nodes of the receiver swapped should
    26  	// be returned, otherwise the receiver should be returned
    27  	// unaltered.
    28  	ReversedEdge() Edge
    29  }
    30  
    31  // WeightedEdge is a weighted graph edge. In directed graphs, the direction
    32  // of the edge is given from -> to, otherwise the edge is semantically
    33  // unordered.
    34  type WeightedEdge interface {
    35  	Edge
    36  	Weight() float64
    37  }
    38  
    39  // Graph is a generalized graph.
    40  type Graph interface {
    41  	// Node returns the node with the given ID if it exists
    42  	// in the graph, and nil otherwise.
    43  	Node(id int64) Node
    44  
    45  	// Nodes returns all the nodes in the graph.
    46  	//
    47  	// Nodes must not return nil.
    48  	Nodes() Nodes
    49  
    50  	// From returns all nodes that can be reached directly
    51  	// from the node with the given ID.
    52  	//
    53  	// From must not return nil.
    54  	From(id int64) Nodes
    55  
    56  	// HasEdgeBetween returns whether an edge exists between
    57  	// nodes with IDs xid and yid without considering direction.
    58  	HasEdgeBetween(xid, yid int64) bool
    59  
    60  	// Edge returns the edge from u to v, with IDs uid and vid,
    61  	// if such an edge exists and nil otherwise. The node v
    62  	// must be directly reachable from u as defined by the
    63  	// From method.
    64  	Edge(uid, vid int64) Edge
    65  }
    66  
    67  // Weighted is a weighted graph.
    68  type Weighted interface {
    69  	Graph
    70  
    71  	// WeightedEdge returns the weighted edge from u to v
    72  	// with IDs uid and vid if such an edge exists and
    73  	// nil otherwise. The node v must be directly
    74  	// reachable from u as defined by the From method.
    75  	WeightedEdge(uid, vid int64) WeightedEdge
    76  
    77  	// Weight returns the weight for the edge between
    78  	// x and y with IDs xid and yid if Edge(xid, yid)
    79  	// returns a non-nil Edge.
    80  	// If x and y are the same node or there is no
    81  	// joining edge between the two nodes the weight
    82  	// value returned is implementation dependent.
    83  	// Weight returns true if an edge exists between
    84  	// x and y or if x and y have the same ID, false
    85  	// otherwise.
    86  	Weight(xid, yid int64) (w float64, ok bool)
    87  }
    88  
    89  // Undirected is an undirected graph.
    90  type Undirected interface {
    91  	Graph
    92  
    93  	// EdgeBetween returns the edge between nodes x and y
    94  	// with IDs xid and yid.
    95  	EdgeBetween(xid, yid int64) Edge
    96  }
    97  
    98  // WeightedUndirected is a weighted undirected graph.
    99  type WeightedUndirected interface {
   100  	Weighted
   101  
   102  	// WeightedEdgeBetween returns the edge between nodes
   103  	// x and y with IDs xid and yid.
   104  	WeightedEdgeBetween(xid, yid int64) WeightedEdge
   105  }
   106  
   107  // Directed is a directed graph.
   108  type Directed interface {
   109  	Graph
   110  
   111  	// HasEdgeFromTo returns whether an edge exists
   112  	// in the graph from u to v with IDs uid and vid.
   113  	HasEdgeFromTo(uid, vid int64) bool
   114  
   115  	// To returns all nodes that can reach directly
   116  	// to the node with the given ID.
   117  	//
   118  	// To must not return nil.
   119  	To(id int64) Nodes
   120  }
   121  
   122  // WeightedDirected is a weighted directed graph.
   123  type WeightedDirected interface {
   124  	Weighted
   125  
   126  	// HasEdgeFromTo returns whether an edge exists
   127  	// in the graph from u to v with the IDs uid and
   128  	// vid.
   129  	HasEdgeFromTo(uid, vid int64) bool
   130  
   131  	// To returns all nodes that can reach directly
   132  	// to the node with the given ID.
   133  	//
   134  	// To must not return nil.
   135  	To(id int64) Nodes
   136  }
   137  
   138  // NodeAdder is an interface for adding arbitrary nodes to a graph.
   139  type NodeAdder interface {
   140  	// NewNode returns a new Node with a unique
   141  	// arbitrary ID.
   142  	NewNode() Node
   143  
   144  	// AddNode adds a node to the graph. AddNode panics if
   145  	// the added node ID matches an existing node ID.
   146  	AddNode(Node)
   147  }
   148  
   149  // NodeWithIDer is a graph that can return potentially new nodes with
   150  // a defined ID.
   151  type NodeWithIDer interface {
   152  	// NodeWithID returns a Node with the given ID if possible.
   153  	// A nil Node will be returned if no Node exists or
   154  	// can be created.
   155  	// If a non-nil Node is returned that is not already in the
   156  	// graph NodeWithID will return true for new and the Node
   157  	// must be added to the graph before use.
   158  	NodeWithID(id int64) (n Node, new bool)
   159  }
   160  
   161  // NodeRemover is an interface for removing nodes from a graph.
   162  type NodeRemover interface {
   163  	// RemoveNode removes the node with the given ID
   164  	// from the graph, as well as any edges attached
   165  	// to it. If the node is not in the graph it is
   166  	// a no-op.
   167  	RemoveNode(id int64)
   168  }
   169  
   170  // EdgeAdder is an interface for adding edges to a graph.
   171  type EdgeAdder interface {
   172  	// NewEdge returns a new Edge from the source to the destination node.
   173  	NewEdge(from, to Node) Edge
   174  
   175  	// SetEdge adds an edge from one node to another.
   176  	// If the graph supports node addition the nodes
   177  	// will be added if they do not exist, otherwise
   178  	// SetEdge will panic.
   179  	// The behavior of an EdgeAdder when the IDs
   180  	// returned by e.From() and e.To() are equal is
   181  	// implementation-dependent.
   182  	// Whether e, e.From() and e.To() are stored
   183  	// within the graph is implementation dependent.
   184  	SetEdge(e Edge)
   185  }
   186  
   187  // WeightedEdgeAdder is an interface for adding edges to a graph.
   188  type WeightedEdgeAdder interface {
   189  	// NewWeightedEdge returns a new WeightedEdge from
   190  	// the source to the destination node.
   191  	NewWeightedEdge(from, to Node, weight float64) WeightedEdge
   192  
   193  	// SetWeightedEdge adds an edge from one node to
   194  	// another. If the graph supports node addition
   195  	// the nodes will be added if they do not exist,
   196  	// otherwise SetWeightedEdge will panic.
   197  	// The behavior of a WeightedEdgeAdder when the IDs
   198  	// returned by e.From() and e.To() are equal is
   199  	// implementation-dependent.
   200  	// Whether e, e.From() and e.To() are stored
   201  	// within the graph is implementation dependent.
   202  	SetWeightedEdge(e WeightedEdge)
   203  }
   204  
   205  // EdgeRemover is an interface for removing nodes from a graph.
   206  type EdgeRemover interface {
   207  	// RemoveEdge removes the edge with the given end
   208  	// IDs, leaving the terminal nodes. If the edge
   209  	// does not exist it is a no-op.
   210  	RemoveEdge(fid, tid int64)
   211  }
   212  
   213  // Builder is a graph that can have nodes and edges added.
   214  type Builder interface {
   215  	NodeAdder
   216  	EdgeAdder
   217  }
   218  
   219  // WeightedBuilder is a graph that can have nodes and weighted edges added.
   220  type WeightedBuilder interface {
   221  	NodeAdder
   222  	WeightedEdgeAdder
   223  }
   224  
   225  // UndirectedBuilder is an undirected graph builder.
   226  type UndirectedBuilder interface {
   227  	Undirected
   228  	Builder
   229  }
   230  
   231  // UndirectedWeightedBuilder is an undirected weighted graph builder.
   232  type UndirectedWeightedBuilder interface {
   233  	Undirected
   234  	WeightedBuilder
   235  }
   236  
   237  // DirectedBuilder is a directed graph builder.
   238  type DirectedBuilder interface {
   239  	Directed
   240  	Builder
   241  }
   242  
   243  // DirectedWeightedBuilder is a directed weighted graph builder.
   244  type DirectedWeightedBuilder interface {
   245  	Directed
   246  	WeightedBuilder
   247  }
   248  
   249  // Copy copies nodes and edges as undirected edges from the source to the destination
   250  // without first clearing the destination. Copy will panic if a node ID in the source
   251  // graph matches a node ID in the destination.
   252  //
   253  // If the source is undirected and the destination is directed both directions will
   254  // be present in the destination after the copy is complete.
   255  func Copy(dst Builder, src Graph) {
   256  	nodes := src.Nodes()
   257  	for nodes.Next() {
   258  		dst.AddNode(nodes.Node())
   259  	}
   260  	nodes.Reset()
   261  	for nodes.Next() {
   262  		u := nodes.Node()
   263  		uid := u.ID()
   264  		to := src.From(uid)
   265  		for to.Next() {
   266  			v := to.Node()
   267  			dst.SetEdge(src.Edge(uid, v.ID()))
   268  		}
   269  	}
   270  }
   271  
   272  // CopyWeighted copies nodes and edges as undirected edges from the source to the destination
   273  // without first clearing the destination. Copy will panic if a node ID in the source
   274  // graph matches a node ID in the destination.
   275  //
   276  // If the source is undirected and the destination is directed both directions will
   277  // be present in the destination after the copy is complete.
   278  //
   279  // If the source is a directed graph, the destination is undirected, and a fundamental
   280  // cycle exists with two nodes where the edge weights differ, the resulting destination
   281  // graph's edge weight between those nodes is undefined. If there is a defined function
   282  // to resolve such conflicts, an UndirectWeighted may be used to do this.
   283  func CopyWeighted(dst WeightedBuilder, src Weighted) {
   284  	nodes := src.Nodes()
   285  	for nodes.Next() {
   286  		dst.AddNode(nodes.Node())
   287  	}
   288  	nodes.Reset()
   289  	for nodes.Next() {
   290  		u := nodes.Node()
   291  		uid := u.ID()
   292  		to := src.From(uid)
   293  		for to.Next() {
   294  			v := to.Node()
   295  			dst.SetWeightedEdge(src.WeightedEdge(uid, v.ID()))
   296  		}
   297  	}
   298  }