diff --git a/cmd/internal/markov/absorbing.go b/cmd/internal/markov/absorbing.go index 3d233d7..c71f242 100644 --- a/cmd/internal/markov/absorbing.go +++ b/cmd/internal/markov/absorbing.go @@ -17,12 +17,9 @@ along with this program. If not, see . package markov import ( - "errors" "math" - "strconv" "gonum.org/v1/gonum/graph" - "gonum.org/v1/gonum/graph/encoding" "gonum.org/v1/gonum/graph/multi" "gonum.org/v1/gonum/graph/simple" "gonum.org/v1/gonum/graph/topo" @@ -158,51 +155,3 @@ func (g *AbsorbingMarkovChain) NewNode() graph.Node { func (g *AbsorbingMarkovChain) SetEdge(e graph.Edge) { g.WeightedDirectedGraph.SetWeightedLine(e.(*weightedEdge)) } - -// weightedEdge is a DOT-aware multi.WeightedLine. By being a -// multi.WeightedLine, it allows for self-loops, which are important for -// absorbing Markov chains. -// TODO: this is a little confusing, maybe just have checks in the code that -// there's only one line in each edge? -type weightedEdge struct { - multi.WeightedLine -} - -// ReversedEdge returns a new weightedEdge with the same weight, but the -// direction reversed. It exists mainly to satisfy the graph.Edge interface. -func (e *weightedEdge) ReversedEdge() graph.Edge { - revLine := multi.WeightedLine{F: e.T, T: e.F, W: e.W} - return &weightedEdge{WeightedLine: revLine} -} - -// SetAttribute enables storing the weight read from a DOT file. It errors if -// an attribute is read that can't be stored in a weightedEdge. -func (e *weightedEdge) SetAttribute(attr encoding.Attribute) error { - var err error - - switch attr.Key { - case "weight": - e.W, err = strconv.ParseFloat(attr.Value, 64) - default: - err = errors.New("unknown key:" + attr.Key) - } - - return err -} - -// Node is a DOT-aware graph.Node. -type Node struct { - graph.Node - dotID string -} - -// SetDOTID sets the node's DOT ID. It enables storing the node name read from -// a DOT file. -func (n *Node) SetDOTID(id string) { - n.dotID = id -} - -// DOTID returns the node's DOT ID. -func (n *Node) DOTID() string { - return n.dotID -} diff --git a/cmd/internal/markov/nodes_edges.go b/cmd/internal/markov/nodes_edges.go new file mode 100644 index 0000000..ad7acf3 --- /dev/null +++ b/cmd/internal/markov/nodes_edges.go @@ -0,0 +1,74 @@ +/* +Copyright © 2025 filifa + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +package markov + +import ( + "errors" + "strconv" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/encoding" + "gonum.org/v1/gonum/graph/multi" +) + +// Node is a DOT-aware graph.Node. +type Node struct { + graph.Node + dotID string +} + +// SetDOTID sets the node's DOT ID. It enables storing the node name read from +// a DOT file. +func (n *Node) SetDOTID(id string) { + n.dotID = id +} + +// DOTID returns the node's DOT ID. +func (n *Node) DOTID() string { + return n.dotID +} + +// weightedEdge is a DOT-aware multi.WeightedLine. By being a +// multi.WeightedLine, it allows for self-loops, which are important for +// absorbing Markov chains. +// TODO: this is a little confusing, maybe just have checks in the code that +// there's only one line in each edge? +type weightedEdge struct { + multi.WeightedLine +} + +// ReversedEdge returns a new weightedEdge with the same weight, but the +// direction reversed. It exists mainly to satisfy the graph.Edge interface. +func (e *weightedEdge) ReversedEdge() graph.Edge { + revLine := multi.WeightedLine{F: e.T, T: e.F, W: e.W} + return &weightedEdge{WeightedLine: revLine} +} + +// SetAttribute enables storing the weight read from a DOT file. It errors if +// an attribute is read that can't be stored in a weightedEdge. +func (e *weightedEdge) SetAttribute(attr encoding.Attribute) error { + var err error + + switch attr.Key { + case "weight": + e.W, err = strconv.ParseFloat(attr.Value, 64) + default: + err = errors.New("unknown key:" + attr.Key) + } + + return err +}