From 4ec04b6abf7b01736fb2e3b566c73cc959f6aee2 Mon Sep 17 00:00:00 2001 From: filifa Date: Fri, 2 May 2025 21:02:05 -0400 Subject: [PATCH] add tests for if graph is absorbing markov chain --- cmd/internal/markov/absorbing.go | 27 +++++++++++++++++++++++++++ cmd/root.go | 4 ++++ 2 files changed, 31 insertions(+) diff --git a/cmd/internal/markov/absorbing.go b/cmd/internal/markov/absorbing.go index 306ca26..a639650 100644 --- a/cmd/internal/markov/absorbing.go +++ b/cmd/internal/markov/absorbing.go @@ -25,6 +25,7 @@ import ( "gonum.org/v1/gonum/graph/encoding" "gonum.org/v1/gonum/graph/multi" "gonum.org/v1/gonum/graph/simple" + "gonum.org/v1/gonum/graph/topo" "gonum.org/v1/gonum/mat" ) @@ -79,6 +80,32 @@ func (g *AbsorbingMarkovChain) AbsorbingNodes() []graph.Node { return absorbingNodes } +func (g *AbsorbingMarkovChain) IsAbsorbing() bool { + absorbingNodes := g.AbsorbingNodes() + if len(absorbingNodes) == 0 { + return false + } + + for nodes := g.Nodes(); nodes.Next(); { + u := nodes.Node() + if !g.canBeAbsorbed(u, absorbingNodes) { + return false + } + } + + return true +} + +func (g *AbsorbingMarkovChain) canBeAbsorbed(u graph.Node, absorbingNodes []graph.Node) bool { + for _, v := range absorbingNodes { + if topo.PathExistsIn(g, u, v) { + return true + } + } + + return false +} + func (g *AbsorbingMarkovChain) AdjacencyMatrix() mat.Matrix { adj := simple.NewDirectedMatrix(g.Nodes().Len(), 0, 0, 0) for edges := g.WeightedEdges(); edges.Next(); { diff --git a/cmd/root.go b/cmd/root.go index 729e040..8dc03e3 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -57,6 +57,10 @@ func parse(cmd *cobra.Command, args []string) { } if !graph.IsValid() { + panic("not a Markov chain!") + } + + if !graph.IsAbsorbing() { panic("not an absorbing Markov chain!") }