func (g *weightedUndirected) AdjacentTo(vertex Vertex, f VertexStep) {
	g.mu.RLock()
	defer g.mu.RUnlock()
	eachVertexInAdjacencyList(g.list, vertex, f)
}
Enumerates the vertices adjacent to the provided vertex.
package al
import (
	"sync"
	. "github.com/sdboyer/gogl"
	"gopkg.in/fatih/set.v0"
)
type baseWeighted struct {
	list map[Vertex]map[Vertex]float64
	size int
	mu   sync.RWMutex
}
func (g *baseWeighted) Vertices(f VertexStep) {
	g.mu.RLock()
	defer g.mu.RUnlock()
	for v := range g.list {
		if f(v) {
			return
		}
	}
}
func (g *baseWeighted) HasVertex(vertex Vertex) (exists bool) {
	g.mu.RLock()
	defer g.mu.RUnlock()
	exists = g.hasVertex(vertex)
	return
}
func (g *baseWeighted) hasVertex(vertex Vertex) (exists bool) {
	_, exists = g.list[vertex]
	return
}
func (g *baseWeighted) Order() int {
	g.mu.RLock()
	defer g.mu.RUnlock()
	return len(g.list)
}
func (g *baseWeighted) Size() int {
	return g.size
}
func (g *baseWeighted) EnsureVertex(vertices ...Vertex) {
	if len(vertices) == 0 {
		return
	}
	g.mu.Lock()
	defer g.mu.Unlock()
	g.ensureVertex(vertices...)
}
func (g *baseWeighted) ensureVertex(vertices ...Vertex) {
	for _, vertex := range vertices {
		if !g.hasVertex(vertex) {
			g.list[vertex] = make(map[Vertex]float64, 10)
		}
	}
	return
}
type weightedDirected struct {
	baseWeighted
}
func (g *weightedDirected) OutDegreeOf(vertex Vertex) (degree int, exists bool) {
	g.mu.RLock()
	defer g.mu.RUnlock()
	if exists = g.hasVertex(vertex); exists {
		degree = len(g.list[vertex])
	}
	return
}
func (g *weightedDirected) InDegreeOf(vertex Vertex) (degree int, exists bool) {
	g.mu.RLock()
	defer g.mu.RUnlock()
	return inDegreeOf(g, vertex)
}
func (g *weightedDirected) DegreeOf(vertex Vertex) (degree int, exists bool) {
	g.mu.RLock()
	defer g.mu.RUnlock()
	indegree, exists := inDegreeOf(g, vertex)
	outdegree, exists := g.OutDegreeOf(vertex)
	return indegree + outdegree, exists
}
func (g *weightedDirected) IncidentTo(v Vertex, f EdgeStep) {
	g.mu.RLock()
	defer g.mu.RUnlock()
	eachEdgeIncidentToDirected(g, v, f)
}
func (g *weightedDirected) AdjacentTo(start Vertex, f VertexStep) {
	g.mu.RLock()
	defer g.mu.RUnlock()
	g.IncidentTo(start, func(e Edge) bool {
		u, v := e.Both()
		if u == start {
			return f(v)
		} else {
			return f(u)
		}
	})
}
func (g *weightedDirected) ArcsFrom(v Vertex, f ArcStep) {
	g.mu.RLock()
	defer g.mu.RUnlock()
	if !g.hasVertex(v) {
		return
	}
	for adjacent, weight := range g.list[v] {
		if f(NewWeightedArc(v, adjacent, weight)) {
			return
		}
	}
}
func (g *weightedDirected) SuccessorsOf(v Vertex, f VertexStep) {
	g.mu.RLock()
	defer g.mu.RUnlock()
	eachVertexInAdjacencyList(g.list, v, f)
}
func (g *weightedDirected) ArcsTo(v Vertex, f ArcStep) {
	g.mu.RLock()
	defer g.mu.RUnlock()
	if !g.hasVertex(v) {
		return
	}
	for candidate, adjacent := range g.list {
		for target, weight := range adjacent {
			if target == v {
				if f(NewWeightedArc(candidate, target, weight)) {
					return
				}
			}
		}
	}
}
func (g *weightedDirected) PredecessorsOf(v Vertex, f VertexStep) {
	g.mu.RLock()
	defer g.mu.RUnlock()
	eachPredecessorOf(g.list, v, f)
}
func (g *weightedDirected) Edges(f EdgeStep) {
	g.mu.RLock()
	defer g.mu.RUnlock()
	for source, adjacent := range g.list {
		for target, weight := range adjacent {
			if f(NewWeightedEdge(source, target, weight)) {
				return
			}
		}
	}
}
func (g *weightedDirected) HasEdge(edge Edge) bool {
	g.mu.RLock()
	defer g.mu.RUnlock()
	u, v := edge.Both()
	_, exists := g.list[u][v]
	if !exists {
		_, exists = g.list[v][u]
	}
	return exists
}
func (g *weightedDirected) HasArc(arc Arc) bool {
	g.mu.RLock()
	defer g.mu.RUnlock()
	_, exists := g.list[arc.Source()][arc.Target()]
	return exists
}
func (g *weightedDirected) HasWeightedEdge(edge WeightedEdge) bool {
	g.mu.RLock()
	defer g.mu.RUnlock()
	u, v := edge.Both()
	if weight, exists := g.list[u][v]; exists {
		return weight == edge.Weight()
	} else if weight, exists = g.list[v][u]; exists {
		return weight == edge.Weight()
	}
	return false
}
func (g *weightedDirected) HasWeightedArc(arc WeightedArc) bool {
	g.mu.RLock()
	defer g.mu.RUnlock()
	if weight, exists := g.list[arc.Source()][arc.Target()]; exists {
		return weight == arc.Weight()
	}
	return false
}
func (g *weightedDirected) Density() float64 {
	g.mu.RLock()
	defer g.mu.RUnlock()
	order := g.Order()
	return float64(g.Size()) / float64(order*(order-1))
}
func (g *weightedDirected) RemoveVertex(vertices ...Vertex) {
	if len(vertices) == 0 {
		return
	}
	g.mu.Lock()
	defer g.mu.Unlock()
	for _, vertex := range vertices {
		if g.hasVertex(vertex) {
			g.size -= len(g.list[vertex])
			delete(g.list, vertex)
			for _, adjacent := range g.list {
				if _, has := adjacent[vertex]; has {
					delete(adjacent, vertex)
					g.size--
				}
			}
		}
	}
	return
}
func (g *weightedDirected) AddArcs(arcs ...WeightedArc) {
	if len(arcs) == 0 {
		return
	}
	g.mu.Lock()
	defer g.mu.Unlock()
	g.addArcs(arcs...)
}
func (g *weightedDirected) addArcs(arcs ...WeightedArc) {
	for _, arc := range arcs {
		g.ensureVertex(arc.Source(), arc.Target())
		if _, exists := g.list[arc.Source()][arc.Target()]; !exists {
			g.list[arc.Source()][arc.Target()] = arc.Weight()
			g.size++
		}
	}
}
func (g *weightedDirected) RemoveArcs(arcs ...WeightedArc) {
	if len(arcs) == 0 {
		return
	}
	g.mu.Lock()
	defer g.mu.Unlock()
	for _, arc := range arcs {
		s, t := arc.Both()
		if _, exists := g.list[s][t]; exists {
			delete(g.list[s], t)
			g.size--
		}
	}
}
func (g *weightedDirected) Transpose() Digraph {
	g.mu.RLock()
	defer g.mu.RUnlock()
	g2 := &weightedDirected{}
	g2.list = make(map[Vertex]map[Vertex]float64)
	startcap := int(g.Size() / g.Order())
	for source, adjacent := range g.list {
		if !g2.hasVertex(source) {
			g2.list[source] = make(map[Vertex]float64, startcap+1)
		}
		for target, weight := range adjacent {
			if !g2.hasVertex(target) {
				g2.list[target] = make(map[Vertex]float64, startcap+1)
			}
			g2.list[target][source] = weight
		}
	}
	return g2
}
type weightedUndirected struct {
	baseWeighted
}
func (g *weightedUndirected) DegreeOf(vertex Vertex) (degree int, exists bool) {
	g.mu.RLock()
	defer g.mu.RUnlock()
	if exists = g.hasVertex(vertex); exists {
		degree = len(g.list[vertex])
	}
	return
}
func (g *weightedUndirected) Edges(f EdgeStep) {
	g.mu.RLock()
	defer g.mu.RUnlock()
	visited := set.New(set.NonThreadSafe)
	var e WeightedEdge
	for source, adjacent := range g.list {
		for target, weight := range adjacent {
			e = NewWeightedEdge(source, target, weight)
			if !visited.Has(NewEdge(e.Both())) {
				visited.Add(NewEdge(target, source))
				if f(e) {
					return
				}
			}
		}
	}
}
func (g *weightedDirected) Arcs(f ArcStep) {
	g.mu.RLock()
	defer g.mu.RUnlock()
	for source, adjacent := range g.list {
		for target, weight := range adjacent {
			if f(NewWeightedArc(source, target, weight)) {
				return
			}
		}
	}
}
func (g *weightedUndirected) IncidentTo(v Vertex, f EdgeStep) {
	g.mu.RLock()
	defer g.mu.RUnlock()
	if !g.hasVertex(v) {
		return
	}
	for adjacent, weight := range g.list[v] {
		if f(NewWeightedEdge(v, adjacent, weight)) {
			return
		}
	}
}