func (g *DirectedMatrix) Weight(xid, yid int64) (w float64, ok bool) {
	if xid == yid {
		return g.self, true
	}
	if g.HasEdgeFromTo(xid, yid) {
		return g.mat.At(int(xid), int(yid)), true
	}
	return g.absent, false
}
Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge.
If x and y are the same node or there is no joining edge between the two nodes the weight
value returned is either the graph's absent or self value. Weight returns true if an edge
exists between x and y or if x and y have the same ID, false otherwise.
package simple
import (
	"sort"
	"gonum.org/v1/gonum/graph"
	"gonum.org/v1/gonum/graph/internal/ordered"
	"gonum.org/v1/gonum/graph/iterator"
	"gonum.org/v1/gonum/mat"
)
var (
	dm *DirectedMatrix
	_ graph.Graph        = dm
	_ graph.Directed     = dm
	_ edgeSetter         = dm
	_ weightedEdgeSetter = dm
)
type DirectedMatrix struct {
	mat   *mat.Dense
	nodes []graph.Node
	self   float64
	absent float64
}
func NewDirectedMatrix(n int, init, self, absent float64) *DirectedMatrix {
	matrix := make([]float64, n*n)
	if init != 0 {
		for i := range matrix {
			matrix[i] = init
		}
	}
	for i := 0; i < len(matrix); i += n + 1 {
		matrix[i] = self
	}
	return &DirectedMatrix{
		mat:    mat.NewDense(n, n, matrix),
		self:   self,
		absent: absent,
	}
}
func NewDirectedMatrixFrom(nodes []graph.Node, init, self, absent float64) *DirectedMatrix {
	sort.Sort(ordered.ByID(nodes))
	for i, n := range nodes {
		if int64(i) != n.ID() {
			panic("simple: non-contiguous node IDs")
		}
	}
	g := NewDirectedMatrix(len(nodes), init, self, absent)
	g.nodes = nodes
	return g
}
func (g *DirectedMatrix) Edge(uid, vid int64) graph.Edge {
	return g.WeightedEdge(uid, vid)
}
func (g *DirectedMatrix) Edges() graph.Edges {
	var edges []graph.Edge
	r, _ := g.mat.Dims()
	for i := 0; i < r; i++ {
		for j := 0; j < r; j++ {
			if i == j {
				continue
			}
			if w := g.mat.At(i, j); !isSame(w, g.absent) {
				edges = append(edges, WeightedEdge{F: g.Node(int64(i)), T: g.Node(int64(j)), W: w})
			}
		}
	}
	if len(edges) == 0 {
		return graph.Empty
	}
	return iterator.NewOrderedEdges(edges)
}
func (g *DirectedMatrix) From(id int64) graph.Nodes {
	if !g.has(id) {
		return graph.Empty
	}
	var nodes []graph.Node
	_, c := g.mat.Dims()
	for j := 0; j < c; j++ {
		if int64(j) == id {
			continue
		}
		if !isSame(g.mat.At(int(id), j), g.absent) {
			nodes = append(nodes, g.Node(int64(j)))
		}
	}
	if len(nodes) == 0 {
		return graph.Empty
	}
	return iterator.NewOrderedNodes(nodes)
}
func (g *DirectedMatrix) HasEdgeBetween(xid, yid int64) bool {
	if !g.has(xid) {
		return false
	}
	if !g.has(yid) {
		return false
	}
	return xid != yid && (!isSame(g.mat.At(int(xid), int(yid)), g.absent) || !isSame(g.mat.At(int(yid), int(xid)), g.absent))
}
func (g *DirectedMatrix) HasEdgeFromTo(uid, vid int64) bool {
	if !g.has(uid) {
		return false
	}
	if !g.has(vid) {
		return false
	}
	return uid != vid && !isSame(g.mat.At(int(uid), int(vid)), g.absent)
}
func (g *DirectedMatrix) Matrix() mat.Matrix {
	m := *g.mat
	return &m
}
func (g *DirectedMatrix) Node(id int64) graph.Node {
	if !g.has(id) {
		return nil
	}
	if g.nodes == nil {
		return Node(id)
	}
	return g.nodes[id]
}
func (g *DirectedMatrix) Nodes() graph.Nodes {
	if g.nodes != nil {
		nodes := make([]graph.Node, len(g.nodes))
		copy(nodes, g.nodes)
		return iterator.NewOrderedNodes(nodes)
	}
	r, _ := g.mat.Dims()
	return iterator.NewImplicitNodes(0, r, newSimpleNode)
}
func (g *DirectedMatrix) RemoveEdge(fid, tid int64) {
	if !g.has(fid) {
		return
	}
	if !g.has(tid) {
		return
	}
	g.mat.Set(int(fid), int(tid), g.absent)
}
func (g *DirectedMatrix) SetEdge(e graph.Edge) {
	g.setWeightedEdge(e, 1)
}
func (g *DirectedMatrix) SetWeightedEdge(e graph.WeightedEdge) {
	g.setWeightedEdge(e, e.Weight())
}
func (g *DirectedMatrix) setWeightedEdge(e graph.Edge, weight float64) {
	from := e.From()
	fid := from.ID()
	to := e.To()
	tid := to.ID()
	if fid == tid {
		panic("simple: set illegal edge")
	}
	if int64(int(fid)) != fid {
		panic("simple: unavailable from node ID for dense graph")
	}
	if int64(int(tid)) != tid {
		panic("simple: unavailable to node ID for dense graph")
	}
	if g.nodes != nil {
		g.nodes[fid] = from
		g.nodes[tid] = to
	}
	g.mat.Set(int(fid), int(tid), weight)
}
func (g *DirectedMatrix) To(id int64) graph.Nodes {
	if !g.has(id) {
		return graph.Empty
	}
	var nodes []graph.Node
	r, _ := g.mat.Dims()
	for i := 0; i < r; i++ {
		if int64(i) == id {
			continue
		}
		if !isSame(g.mat.At(i, int(id)), g.absent) {
			nodes = append(nodes, g.Node(int64(i)))
		}
	}
	if len(nodes) == 0 {
		return graph.Empty
	}
	return iterator.NewOrderedNodes(nodes)
}