blob: e3dd4d747f43aa6f7128994dcae6e02b43501c6b [file] [edit]
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package graphalg
import "github.com/aclements/go-moremath/graph"
// SimplifyMulti simplifies a multigraph to a weighted simple graph.
//
// If g is a weighted graph, each edge in the result receives the sum
// of the weights of the combined edges in g. If g is not weighted,
// each edge in g is assumed to have a weight of 1.
func SimplifyMulti(g graph.Graph) graph.Weighted {
gw, ok := g.(graph.Weighted)
if !ok {
gw = graph.WeightedUnit{g}
}
indexes := make([]int, gw.NumNodes()+1)
var edges []int
var weights []float64
edgeMap := make(map[int]int)
for n := range indexes[1:] {
for k := range edgeMap {
delete(edgeMap, k)
}
for i, o := range gw.Out(n) {
if idx, ok := edgeMap[o]; ok {
// Already have an edge.
weights[idx] += gw.OutWeight(n, i)
} else {
edgeMap[o] = len(edges)
edges = append(edges, o)
weights = append(weights, gw.OutWeight(n, i))
}
}
indexes[n+1] = len(edges)
}
return &simplified{indexes, edges, weights}
}
type simplified struct {
indexes []int
edges []int
weights []float64
}
func (g *simplified) NumNodes() int {
return len(g.indexes) - 1
}
func (g *simplified) Out(n int) []int {
return g.edges[g.indexes[n]:g.indexes[n+1]]
}
func (g *simplified) OutWeight(n, e int) float64 {
return g.weights[g.indexes[n]:g.indexes[n+1]][e]
}