github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/graph/simple/undirected.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 simple
     6  
     7  import (
     8  	"fmt"
     9  
    10  	"github.com/jingcheng-WU/gonum/graph"
    11  	"github.com/jingcheng-WU/gonum/graph/iterator"
    12  	"github.com/jingcheng-WU/gonum/graph/set/uid"
    13  )
    14  
    15  var (
    16  	ug *UndirectedGraph
    17  
    18  	_ graph.Graph       = ug
    19  	_ graph.Undirected  = ug
    20  	_ graph.NodeAdder   = ug
    21  	_ graph.NodeRemover = ug
    22  	_ graph.EdgeAdder   = ug
    23  	_ graph.EdgeRemover = ug
    24  )
    25  
    26  // UndirectedGraph implements a generalized undirected graph.
    27  type UndirectedGraph struct {
    28  	nodes map[int64]graph.Node
    29  	edges map[int64]map[int64]graph.Edge
    30  
    31  	nodeIDs *uid.Set
    32  }
    33  
    34  // NewUndirectedGraph returns an UndirectedGraph.
    35  func NewUndirectedGraph() *UndirectedGraph {
    36  	return &UndirectedGraph{
    37  		nodes: make(map[int64]graph.Node),
    38  		edges: make(map[int64]map[int64]graph.Edge),
    39  
    40  		nodeIDs: uid.NewSet(),
    41  	}
    42  }
    43  
    44  // AddNode adds n to the graph. It panics if the added node ID matches an existing node ID.
    45  func (g *UndirectedGraph) AddNode(n graph.Node) {
    46  	if _, exists := g.nodes[n.ID()]; exists {
    47  		panic(fmt.Sprintf("simple: node ID collision: %d", n.ID()))
    48  	}
    49  	g.nodes[n.ID()] = n
    50  	g.nodeIDs.Use(n.ID())
    51  }
    52  
    53  // Edge returns the edge from u to v if such an edge exists and nil otherwise.
    54  // The node v must be directly reachable from u as defined by the From method.
    55  func (g *UndirectedGraph) Edge(uid, vid int64) graph.Edge {
    56  	return g.EdgeBetween(uid, vid)
    57  }
    58  
    59  // EdgeBetween returns the edge between nodes x and y.
    60  func (g *UndirectedGraph) EdgeBetween(xid, yid int64) graph.Edge {
    61  	edge, ok := g.edges[xid][yid]
    62  	if !ok {
    63  		return nil
    64  	}
    65  	if edge.From().ID() == xid {
    66  		return edge
    67  	}
    68  	return edge.ReversedEdge()
    69  }
    70  
    71  // Edges returns all the edges in the graph.
    72  func (g *UndirectedGraph) Edges() graph.Edges {
    73  	if len(g.edges) == 0 {
    74  		return graph.Empty
    75  	}
    76  	var edges []graph.Edge
    77  	seen := make(map[[2]int64]struct{})
    78  	for _, u := range g.edges {
    79  		for _, e := range u {
    80  			uid := e.From().ID()
    81  			vid := e.To().ID()
    82  			if _, ok := seen[[2]int64{uid, vid}]; ok {
    83  				continue
    84  			}
    85  			seen[[2]int64{uid, vid}] = struct{}{}
    86  			seen[[2]int64{vid, uid}] = struct{}{}
    87  			edges = append(edges, e)
    88  		}
    89  	}
    90  	if len(edges) == 0 {
    91  		return graph.Empty
    92  	}
    93  	return iterator.NewOrderedEdges(edges)
    94  }
    95  
    96  // From returns all nodes in g that can be reached directly from n.
    97  //
    98  // The returned graph.Nodes is only valid until the next mutation of
    99  // the receiver.
   100  func (g *UndirectedGraph) From(id int64) graph.Nodes {
   101  	if len(g.edges[id]) == 0 {
   102  		return graph.Empty
   103  	}
   104  	return iterator.NewNodesByEdge(g.nodes, g.edges[id])
   105  }
   106  
   107  // HasEdgeBetween returns whether an edge exists between nodes x and y.
   108  func (g *UndirectedGraph) HasEdgeBetween(xid, yid int64) bool {
   109  	_, ok := g.edges[xid][yid]
   110  	return ok
   111  }
   112  
   113  // NewEdge returns a new Edge from the source to the destination node.
   114  func (g *UndirectedGraph) NewEdge(from, to graph.Node) graph.Edge {
   115  	return Edge{F: from, T: to}
   116  }
   117  
   118  // NewNode returns a new unique Node to be added to g. The Node's ID does
   119  // not become valid in g until the Node is added to g.
   120  func (g *UndirectedGraph) NewNode() graph.Node {
   121  	if len(g.nodes) == 0 {
   122  		return Node(0)
   123  	}
   124  	if int64(len(g.nodes)) == uid.Max {
   125  		panic("simple: cannot allocate node: no slot")
   126  	}
   127  	return Node(g.nodeIDs.NewID())
   128  }
   129  
   130  // Node returns the node with the given ID if it exists in the graph,
   131  // and nil otherwise.
   132  func (g *UndirectedGraph) Node(id int64) graph.Node {
   133  	return g.nodes[id]
   134  }
   135  
   136  // Nodes returns all the nodes in the graph.
   137  //
   138  // The returned graph.Nodes is only valid until the next mutation of
   139  // the receiver.
   140  func (g *UndirectedGraph) Nodes() graph.Nodes {
   141  	if len(g.nodes) == 0 {
   142  		return graph.Empty
   143  	}
   144  	return iterator.NewNodes(g.nodes)
   145  }
   146  
   147  // NodeWithID returns a Node with the given ID if possible. If a graph.Node
   148  // is returned that is not already in the graph NodeWithID will return true
   149  // for new and the graph.Node must be added to the graph before use.
   150  func (g *UndirectedGraph) NodeWithID(id int64) (n graph.Node, new bool) {
   151  	n, ok := g.nodes[id]
   152  	if ok {
   153  		return n, false
   154  	}
   155  	return Node(id), true
   156  }
   157  
   158  // RemoveEdge removes the edge with the given end IDs from the graph, leaving the terminal nodes.
   159  // If the edge does not exist it is a no-op.
   160  func (g *UndirectedGraph) RemoveEdge(fid, tid int64) {
   161  	if _, ok := g.nodes[fid]; !ok {
   162  		return
   163  	}
   164  	if _, ok := g.nodes[tid]; !ok {
   165  		return
   166  	}
   167  
   168  	delete(g.edges[fid], tid)
   169  	delete(g.edges[tid], fid)
   170  }
   171  
   172  // RemoveNode removes the node with the given ID from the graph, as well as any edges attached
   173  // to it. If the node is not in the graph it is a no-op.
   174  func (g *UndirectedGraph) RemoveNode(id int64) {
   175  	if _, ok := g.nodes[id]; !ok {
   176  		return
   177  	}
   178  	delete(g.nodes, id)
   179  
   180  	for from := range g.edges[id] {
   181  		delete(g.edges[from], id)
   182  	}
   183  	delete(g.edges, id)
   184  
   185  	g.nodeIDs.Release(id)
   186  }
   187  
   188  // SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added
   189  // and are set to the nodes of the edge otherwise.
   190  // It will panic if the IDs of the e.From and e.To are equal.
   191  func (g *UndirectedGraph) SetEdge(e graph.Edge) {
   192  	var (
   193  		from = e.From()
   194  		fid  = from.ID()
   195  		to   = e.To()
   196  		tid  = to.ID()
   197  	)
   198  
   199  	if fid == tid {
   200  		panic("simple: adding self edge")
   201  	}
   202  
   203  	if _, ok := g.nodes[fid]; !ok {
   204  		g.AddNode(from)
   205  	} else {
   206  		g.nodes[fid] = from
   207  	}
   208  	if _, ok := g.nodes[tid]; !ok {
   209  		g.AddNode(to)
   210  	} else {
   211  		g.nodes[tid] = to
   212  	}
   213  
   214  	if fm, ok := g.edges[fid]; ok {
   215  		fm[tid] = e
   216  	} else {
   217  		g.edges[fid] = map[int64]graph.Edge{tid: e}
   218  	}
   219  	if tm, ok := g.edges[tid]; ok {
   220  		tm[fid] = e
   221  	} else {
   222  		g.edges[tid] = map[int64]graph.Edge{fid: e}
   223  	}
   224  }