diff --git a/cmd/internal/graph/common.go b/cmd/internal/graph/common.go new file mode 100644 index 0000000..92259cf --- /dev/null +++ b/cmd/internal/graph/common.go @@ -0,0 +1,68 @@ +/* +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 graph + +import ( + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/mat" +) + +type WeightedGraph interface { + graph.Weighted + + WeightedEdges() graph.WeightedEdges + + AdjacencyMatrix() *mat.Dense +} + +type WeightedMatrix interface { + graph.Weighted + + SetWeightedEdge(e graph.WeightedEdge) + Matrix() mat.Matrix +} + +func toAdjMatrix(g WeightedGraph, adj WeightedMatrix) *mat.Dense { + copyEdges(g, adj) + matrix := mat.DenseCopyOf(adj.Matrix()) + addSelfEdges(g, matrix) + + return matrix +} + +func copyEdges(g WeightedGraph, adj WeightedMatrix) { + for edges := g.WeightedEdges(); edges.Next(); { + e := edges.WeightedEdge() + if e.From() == e.To() { + continue + } + + adj.SetWeightedEdge(e) + } +} + +func addSelfEdges(g WeightedGraph, matrix mat.Mutable) { + nodes := g.Nodes() + for i := 0; nodes.Next(); i++ { + u := nodes.Node() + + e := g.WeightedEdge(u.ID(), u.ID()) + if e != nil { + matrix.Set(i, i, e.Weight()) + } + } +} diff --git a/cmd/internal/graph/graph.go b/cmd/internal/graph/directed.go similarity index 77% rename from cmd/internal/graph/graph.go rename to cmd/internal/graph/directed.go index 7ab1372..8a71b06 100644 --- a/cmd/internal/graph/graph.go +++ b/cmd/internal/graph/directed.go @@ -36,27 +36,6 @@ func NewDirectedGraph() *DirectedGraph { // AdjacencyMatrix returns the graph's adjacency matrix. func (g *DirectedGraph) AdjacencyMatrix() *mat.Dense { adj := simple.NewDirectedMatrix(g.Nodes().Len(), 0, 0, 0) - for edges := g.WeightedEdges(); edges.Next(); { - e := edges.WeightedEdge() - if e.From() == e.To() { - continue - } - - adj.SetWeightedEdge(e) - } - - a := mat.DenseCopyOf(adj.Matrix()) - - nodes := adj.Nodes() - for i := 0; nodes.Next(); i++ { - id := nodes.Node().ID() - u := g.Node(id) - - e := g.WeightedEdge(u.ID(), u.ID()) - if e != nil { - a.Set(i, i, e.Weight()) - } - } - - return a + matrix := toAdjMatrix(g, adj) + return matrix } diff --git a/cmd/internal/graph/undirected.go b/cmd/internal/graph/undirected.go new file mode 100644 index 0000000..a4ef291 --- /dev/null +++ b/cmd/internal/graph/undirected.go @@ -0,0 +1,41 @@ +/* +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 graph + +import ( + "gonum.org/v1/gonum/graph/multi" + "gonum.org/v1/gonum/graph/simple" + "gonum.org/v1/gonum/mat" +) + +// UndirectedGraph embeds a multi.WeightedUndirectedGraph (as opposed to +// simple.WeightedUndirectedGraph) to handle self loops. +type UndirectedGraph struct { + *multi.WeightedUndirectedGraph +} + +// NewUndirectedGraph returns a graph with no nodes or edges. +func NewUndirectedGraph() *UndirectedGraph { + return &UndirectedGraph{WeightedUndirectedGraph: multi.NewWeightedUndirectedGraph()} +} + +// AdjacencyMatrix returns the graph's adjacency matrix. +func (g *UndirectedGraph) AdjacencyMatrix() *mat.Dense { + adj := simple.NewUndirectedMatrix(g.Nodes().Len(), 0, 0, 0) + matrix := toAdjMatrix(g, adj) + return matrix +}