use multigraph implementation to handle self loops
This commit is contained in:
parent
dee62e55a5
commit
241cf1a9d0
|
@ -23,22 +23,23 @@ import (
|
||||||
|
|
||||||
"gonum.org/v1/gonum/graph"
|
"gonum.org/v1/gonum/graph"
|
||||||
"gonum.org/v1/gonum/graph/encoding"
|
"gonum.org/v1/gonum/graph/encoding"
|
||||||
|
"gonum.org/v1/gonum/graph/multi"
|
||||||
"gonum.org/v1/gonum/graph/simple"
|
"gonum.org/v1/gonum/graph/simple"
|
||||||
"gonum.org/v1/gonum/mat"
|
"gonum.org/v1/gonum/mat"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AbsorbingMarkovChain struct {
|
type AbsorbingMarkovChain struct {
|
||||||
*simple.WeightedDirectedGraph
|
*multi.WeightedDirectedGraph
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAbsorbingMarkovChain() *AbsorbingMarkovChain {
|
func NewAbsorbingMarkovChain() *AbsorbingMarkovChain {
|
||||||
return &AbsorbingMarkovChain{WeightedDirectedGraph: simple.NewWeightedDirectedGraph(math.NaN(), 0)}
|
return &AbsorbingMarkovChain{WeightedDirectedGraph: multi.NewWeightedDirectedGraph()}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *AbsorbingMarkovChain) IsValid() bool {
|
func (g *AbsorbingMarkovChain) IsValid() bool {
|
||||||
for nodes := g.Nodes(); nodes.Next(); {
|
for nodes := g.Nodes(); nodes.Next(); {
|
||||||
u := nodes.Node().(*node)
|
u := nodes.Node().(*node)
|
||||||
if g.outWeightSum(u) > 1 {
|
if g.outWeightSum(u) != 1 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +53,7 @@ func (g *AbsorbingMarkovChain) outWeightSum(u graph.Node) float64 {
|
||||||
v := nodes.Node()
|
v := nodes.Node()
|
||||||
e := g.WeightedEdge(u.ID(), v.ID())
|
e := g.WeightedEdge(u.ID(), v.ID())
|
||||||
if e != nil {
|
if e != nil {
|
||||||
sum += e.(*weightedEdge).W
|
sum += e.Weight()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,9 +61,14 @@ func (g *AbsorbingMarkovChain) outWeightSum(u graph.Node) float64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *AbsorbingMarkovChain) AdjacencyMatrix() mat.Matrix {
|
func (g *AbsorbingMarkovChain) AdjacencyMatrix() mat.Matrix {
|
||||||
adj := simple.NewDirectedMatrix(g.Nodes().Len(), 0, math.NaN(), 0)
|
adj := simple.NewDirectedMatrix(g.Nodes().Len(), 0, 0, 0)
|
||||||
for edges := g.WeightedEdges(); edges.Next(); {
|
for edges := g.WeightedEdges(); edges.Next(); {
|
||||||
adj.SetWeightedEdge(edges.WeightedEdge())
|
e := edges.WeightedEdge()
|
||||||
|
if e.From() == e.To() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
adj.SetWeightedEdge(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
a := mat.DenseCopyOf(adj.Matrix())
|
a := mat.DenseCopyOf(adj.Matrix())
|
||||||
|
@ -71,15 +77,19 @@ func (g *AbsorbingMarkovChain) AdjacencyMatrix() mat.Matrix {
|
||||||
for i := 0; nodes.Next(); i++ {
|
for i := 0; nodes.Next(); i++ {
|
||||||
id := nodes.Node().ID()
|
id := nodes.Node().ID()
|
||||||
u := g.Node(id).(*node)
|
u := g.Node(id).(*node)
|
||||||
a.Set(i, i, 1-g.outWeightSum(u))
|
|
||||||
|
e := g.WeightedEdge(u.ID(), u.ID())
|
||||||
|
if e != nil {
|
||||||
|
a.Set(i, i, e.Weight())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *AbsorbingMarkovChain) NewEdge(from, to graph.Node) graph.Edge {
|
func (g *AbsorbingMarkovChain) NewEdge(from, to graph.Node) graph.Edge {
|
||||||
e := g.WeightedDirectedGraph.NewWeightedEdge(from, to, math.NaN()).(simple.WeightedEdge)
|
e := g.WeightedDirectedGraph.NewWeightedLine(from, to, math.NaN()).(multi.WeightedLine)
|
||||||
return &weightedEdge{WeightedEdge: e}
|
return &weightedEdge{WeightedLine: e}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *AbsorbingMarkovChain) NewNode() graph.Node {
|
func (g *AbsorbingMarkovChain) NewNode() graph.Node {
|
||||||
|
@ -87,11 +97,16 @@ func (g *AbsorbingMarkovChain) NewNode() graph.Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *AbsorbingMarkovChain) SetEdge(e graph.Edge) {
|
func (g *AbsorbingMarkovChain) SetEdge(e graph.Edge) {
|
||||||
g.WeightedDirectedGraph.SetWeightedEdge(e.(*weightedEdge))
|
g.WeightedDirectedGraph.SetWeightedLine(e.(*weightedEdge))
|
||||||
}
|
}
|
||||||
|
|
||||||
type weightedEdge struct {
|
type weightedEdge struct {
|
||||||
simple.WeightedEdge
|
multi.WeightedLine
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *weightedEdge) ReversedEdge() graph.Edge {
|
||||||
|
revLine := multi.WeightedLine{F: e.T, T: e.F, W: e.W}
|
||||||
|
return &weightedEdge{WeightedLine: revLine}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *weightedEdge) SetAttribute(attr encoding.Attribute) error {
|
func (e *weightedEdge) SetAttribute(attr encoding.Attribute) error {
|
||||||
|
|
Loading…
Reference in New Issue