func (g *UndirectedGraph) Degree(n graph.Node) int { if _, ok := g.nodeMap[n.ID()]; !ok { return 0 } return len(g.neighbors[n.ID()]) }
// Builds a BFS tree (as a directed graph) from the given graph and start node. func BFSTree(g graph.Graph, start graph.Node) *simple.DirectedGraph { if !g.Has(start) { panic(fmt.Sprintf("BFSTree: Start node %r not in graph %r", start, g)) } ret := simple.NewDirectedGraph(0.0, math.Inf(1)) seen := make(map[int]bool) q := queue.New() q.Add(start) ret.AddNode(simple.Node(start.ID())) for q.Length() > 0 { node := q.Peek().(graph.Node) q.Remove() for _, neighbor := range g.From(node) { if !seen[neighbor.ID()] { seen[neighbor.ID()] = true ret.AddNode(simple.Node(neighbor.ID())) ret.SetEdge(simple.Edge{F: simple.Node(node.ID()), T: simple.Node(neighbor.ID()), W: g.Edge(node, neighbor).Weight()}) q.Add(neighbor) } } } return ret }
// NewImagePipelineFromImageTagLocation returns the ImagePipeline and all the nodes contributing to it func NewImagePipelineFromImageTagLocation(g osgraph.Graph, node graph.Node, imageTagLocation ImageTagLocation) (ImagePipeline, IntSet) { covered := IntSet{} covered.Insert(node.ID()) flow := ImagePipeline{} flow.Image = imageTagLocation for _, input := range g.PredecessorNodesByEdgeKind(node, buildedges.BuildOutputEdgeKind) { covered.Insert(input.ID()) build := input.(*buildgraph.BuildConfigNode) if flow.Build != nil { // report this as an error (unexpected duplicate input build) } if build.BuildConfig == nil { // report this as as a missing build / broken link break } base, src, coveredInputs, _ := findBuildInputs(g, build) covered.Insert(coveredInputs.List()...) flow.Build = build flow.BaseImage = base flow.Source = src } return flow, covered }
// XY returns the cartesian coordinates of n. If n is not a node // in the grid, (NaN, NaN) is returned. func (l *LimitedVisionGrid) XY(n graph.Node) (x, y float64) { if !l.Has(n) { return math.NaN(), math.NaN() } r, c := l.RowCol(n.ID()) return float64(c), float64(r) }
func (g *GraphNode) From(n graph.Node) []graph.Node { if n.ID() == g.ID() { return g.neighbors } visited := map[int]struct{}{g.id: struct{}{}} for _, root := range g.roots { visited[root.ID()] = struct{}{} if result := root.findNeighbors(n, visited); result != nil { return result } } for _, neigh := range g.neighbors { visited[neigh.ID()] = struct{}{} if gn, ok := neigh.(*GraphNode); ok { if result := gn.findNeighbors(n, visited); result != nil { return result } } } return nil }
func (g *GraphNode) findNeighbors(n graph.Node, visited map[int]struct{}) []graph.Node { if n.ID() == g.ID() { return g.neighbors } for _, root := range g.roots { if _, ok := visited[root.ID()]; ok { continue } visited[root.ID()] = struct{}{} if result := root.findNeighbors(n, visited); result != nil { return result } } for _, neigh := range g.neighbors { if _, ok := visited[neigh.ID()]; ok { continue } visited[neigh.ID()] = struct{}{} if gn, ok := neigh.(*GraphNode); ok { if result := gn.findNeighbors(n, visited); result != nil { return result } } } return nil }
// Walk performs a depth-first traversal of the graph g starting from the given node, // depending on the the EdgeFilter field and the until parameter if they are non-nil. The // traversal follows edges for which EdgeFilter(edge) is true and returns the first node // for which until(node) is true. During the traversal, if the Visit field is non-nil, it // is called with the nodes joined by each followed edge. func (d *DepthFirst) Walk(g graph.Graph, from graph.Node, until func(graph.Node) bool) graph.Node { if d.visited == nil { d.visited = &intsets.Sparse{} } d.stack.Push(from) d.visited.Insert(from.ID()) for d.stack.Len() > 0 { t := d.stack.Pop() if until != nil && until(t) { return t } for _, n := range g.From(t) { if d.EdgeFilter != nil && !d.EdgeFilter(g.Edge(t, n)) { continue } if d.visited.Has(n.ID()) { continue } if d.Visit != nil { d.Visit(t, n) } d.visited.Insert(n.ID()) d.stack.Push(n) } } return nil }
// NewImagePipelineFromImageTagLocation returns the ImagePipeline and all the nodes contributing to it func NewImagePipelineFromImageTagLocation(g osgraph.Graph, node graph.Node, imageTagLocation ImageTagLocation) (ImagePipeline, IntSet) { covered := IntSet{} covered.Insert(node.ID()) flow := ImagePipeline{} flow.Image = imageTagLocation for _, input := range g.PredecessorNodesByEdgeKind(node, buildedges.BuildOutputEdgeKind) { covered.Insert(input.ID()) build := input.(*buildgraph.BuildConfigNode) if flow.Build != nil { // report this as an error (unexpected duplicate input build) } if build.BuildConfig == nil { // report this as as a missing build / broken link break } base, src, coveredInputs, _ := findBuildInputs(g, build) covered.Insert(coveredInputs.List()...) flow.BaseImage = base flow.Source = src flow.Build = build flow.LastSuccessfulBuild, flow.LastUnsuccessfulBuild, flow.ActiveBuilds = buildedges.RelevantBuilds(g, flow.Build) } for _, input := range g.SuccessorNodesByEdgeKind(node, imageedges.ReferencedImageStreamGraphEdgeKind) { covered.Insert(input.ID()) imageStreamNode := input.(*imagegraph.ImageStreamNode) flow.DestinationResolved = (len(imageStreamNode.Status.DockerImageRepository) != 0) } return flow, covered }
func (g *DenseGraph) EdgeTo(n, succ graph.Node) graph.Edge { if g.adjacencyMatrix[n.ID()*g.numNodes+succ.ID()] != inf { return Edge{n, succ} } return nil }
func coordinatesForID(n graph.Node, c, r int) [2]int { id := n.ID() if id >= c*r { panic("out of range") } return [2]int{id / r, id % r} }
// XY returns the cartesian coordinates of n. If n is not a node // in the grid, (NaN, NaN) is returned. func (g *Grid) XY(n graph.Node) (x, y float64) { if !g.Has(n) { return math.NaN(), math.NaN() } r, c := g.RowCol(n.ID()) return float64(c), float64(r) }
// key returns the key for the node u and whether the node is // in the queue. If the node is not in the queue, key is returned // as +Inf. func (q *primQueue) key(u graph.Node) (key float64, ok bool) { i, ok := q.indexOf[u.ID()] if !ok { return math.Inf(1), false } return q.nodes[i].Weight(), ok }
// WeightTo returns the weight of the minimum path to v. func (p Shortest) WeightTo(v graph.Node) float64 { to, toOK := p.indexOf[v.ID()] if !toOK { return math.Inf(1) } return p.dist[to] }
func newShortestFrom(u graph.Node, nodes []graph.Node) Shortest { indexOf := make(map[int]int, len(nodes)) uid := u.ID() for i, n := range nodes { indexOf[n.ID()] = i if n.ID() == uid { u = n } } p := Shortest{ from: u, nodes: nodes, indexOf: indexOf, dist: make([]float64, len(nodes)), next: make([]int, len(nodes)), } for i := range nodes { p.dist[i] = math.Inf(1) p.next[i] = -1 } p.dist[indexOf[uid]] = 0 return p }
// From returns all nodes in g that can be reached directly from u. func (g *ReducedUndirected) From(u graph.Node) []graph.Node { out := g.edges[u.ID()] nodes := make([]graph.Node, len(out)) for i, vid := range out { nodes[i] = g.nodes[vid] } return nodes }
func (g *TileGraph) HasEdge(u, v graph.Node) bool { if !g.Has(u) || !g.Has(v) { return false } r1, c1 := g.IDToCoords(u.ID()) r2, c2 := g.IDToCoords(v.ID()) return (c1 == c2 && (r2 == r1+1 || r2 == r1-1)) || (r1 == r2 && (c2 == c1+1 || c2 == c1-1)) }
// Weight returns the weight of the minimum path between u and v. func (p AllShortest) Weight(u, v graph.Node) float64 { from, fromOK := p.indexOf[u.ID()] to, toOK := p.indexOf[v.ID()] if !fromOK || !toOK { return math.Inf(1) } return p.dist.At(from, to) }
func nodeID(n graph.Node) string { switch n := n.(type) { case Node: return n.DOTID() default: return fmt.Sprint(n.ID()) } }
// Adds a node to the graph. Implementation note: if you add a node close to or at // the max int on your machine NewNode will become slower. func (g *DirectedGraph) AddNode(n graph.Node) { g.nodeMap[n.ID()] = n g.successors[n.ID()] = make(map[int]WeightedEdge) g.predecessors[n.ID()] = make(map[int]WeightedEdge) delete(g.freeMap, n.ID()) g.maxID = max(g.maxID, n.ID()) }
func (g *UndirectedGraph) EdgeBetween(u, v graph.Node) graph.Edge { // We don't need to check if neigh exists because // it's implicit in the neighbors access. if !g.Has(u) { return nil } return g.neighbors[u.ID()][v.ID()] }
func (g *Graph) EdgeBetween(n, neigh graph.Node) graph.Edge { // Don't need to check if neigh exists because // it's implicit in the neighbors access. if !g.NodeExists(n) { return nil } return g.neighbors[n.ID()][neigh.ID()] }
// EdgeBetween returns the edge between nodes x and y. func (g *UndirectedGraph) EdgeBetween(x, y graph.Node) graph.Edge { // We don't need to check if neigh exists because // it's implicit in the edges access. if !g.Has(x) { return nil } return g.edges[x.ID()][y.ID()] }
// update updates u's position in the queue with the new closest // MST-connected neighbour, v, and the key weight between u and v. func (q *primQueue) update(u, v graph.Node, key float64) { id := u.ID() i, ok := q.indexOf[id] if !ok { return } q.nodes[i].T = v q.nodes[i].W = key heap.Fix(q, i) }
func (d *DStarLite) worldNodeFor(n graph.Node) *dStarLiteNode { switch w := d.model.Node(n.ID()).(type) { case *dStarLiteNode: return w case graph.Node: panic(fmt.Sprintf("D* Lite: illegal world model node type: %T", w)) default: return newDStarLiteNode(n) } }
func (g *DenseGraph) Successors(n graph.Node) []graph.Node { neighbors := make([]graph.Node, 0) for i := 0; i < g.numNodes; i++ { if g.adjacencyMatrix[n.ID()*g.numNodes+i] != inf { neighbors = append(neighbors, Node(i)) } } return neighbors }
func (g typedGraph) Name(node graph.Node) string { switch t := node.(type) { case fmt.Stringer: return t.String() case uniqueNamer: return t.UniqueName().String() default: return fmt.Sprintf("<unknown:%d>", node.ID()) } }
func (g *DirectedDenseGraph) Weight(x, y graph.Node) (w float64, ok bool) { xid := x.ID() yid := y.ID() if xid == yid { return 0, true } if g.has(xid) && g.has(yid) { return g.mat.At(xid, yid), true } return g.absent, false }
// HasEdgeFromTo returns whether an edge exists in the graph from u to v. func (g *DirectedMatrix) HasEdgeFromTo(u, v graph.Node) bool { uid := u.ID() if !g.has(uid) { return false } vid := v.ID() if !g.has(vid) { return false } return uid != vid && !isSame(g.mat.At(uid, vid), g.absent) }
// HasEdgeBetween returns whether an edge exists between nodes x and y without // considering direction. func (g *DirectedMatrix) HasEdgeBetween(x, y graph.Node) bool { xid := x.ID() if !g.has(xid) { return false } yid := y.ID() if !g.has(yid) { return false } return xid != yid && (!isSame(g.mat.At(xid, yid), g.absent) || !isSame(g.mat.At(yid, xid), g.absent)) }
// BellmanFordFrom returns a shortest-path tree for a shortest path from u to all nodes in // the graph g, or false indicating that a negative cycle exists in the graph. If the graph // does not implement graph.Weighter, UniformCost is used. // // The time complexity of BellmanFordFrom is O(|V|.|E|). func BellmanFordFrom(u graph.Node, g graph.Graph) (path Shortest, ok bool) { if !g.Has(u) { return Shortest{from: u}, true } var weight Weighting if wg, ok := g.(graph.Weighter); ok { weight = wg.Weight } else { weight = UniformCost(g) } nodes := g.Nodes() path = newShortestFrom(u, nodes) path.dist[path.indexOf[u.ID()]] = 0 // TODO(kortschak): Consider adding further optimisations // from http://arxiv.org/abs/1111.5414. for i := 1; i < len(nodes); i++ { changed := false for j, u := range nodes { for _, v := range g.From(u) { k := path.indexOf[v.ID()] w, ok := weight(u, v) if !ok { panic("bellman-ford: unexpected invalid weight") } joint := path.dist[j] + w if joint < path.dist[k] { path.set(k, joint, j) changed = true } } } if !changed { break } } for j, u := range nodes { for _, v := range g.From(u) { k := path.indexOf[v.ID()] w, ok := weight(u, v) if !ok { panic("bellman-ford: unexpected invalid weight") } if path.dist[j]+w < path.dist[k] { return path, false } } } return path, true }