forked from LaconicNetwork/kompose
270 lines
5.7 KiB
Go
270 lines
5.7 KiB
Go
// Copyright ©2014 The gonum 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 concrete
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/gonum/graph"
|
|
)
|
|
|
|
// A Directed graph is a highly generalized MutableDirectedGraph.
|
|
//
|
|
// In most cases it's likely more desireable to use a graph specific to your
|
|
// problem domain.
|
|
type DirectedGraph struct {
|
|
successors map[int]map[int]WeightedEdge
|
|
predecessors map[int]map[int]WeightedEdge
|
|
nodeMap map[int]graph.Node
|
|
|
|
// Add/remove convenience variables
|
|
maxID int
|
|
freeMap map[int]struct{}
|
|
}
|
|
|
|
func NewDirectedGraph() *DirectedGraph {
|
|
return &DirectedGraph{
|
|
successors: make(map[int]map[int]WeightedEdge),
|
|
predecessors: make(map[int]map[int]WeightedEdge),
|
|
nodeMap: make(map[int]graph.Node),
|
|
maxID: 0,
|
|
freeMap: make(map[int]struct{}),
|
|
}
|
|
}
|
|
|
|
func (g *DirectedGraph) NewNodeID() int {
|
|
if g.maxID != maxInt {
|
|
g.maxID++
|
|
return g.maxID
|
|
}
|
|
|
|
// Implicitly checks if len(g.freeMap) == 0
|
|
for id := range g.freeMap {
|
|
return id
|
|
}
|
|
|
|
// I cannot foresee this ever happening, but just in case
|
|
if len(g.nodeMap) == maxInt {
|
|
panic("cannot allocate node: graph too large")
|
|
}
|
|
|
|
for i := 0; i < maxInt; i++ {
|
|
if _, ok := g.nodeMap[i]; !ok {
|
|
return i
|
|
}
|
|
}
|
|
|
|
// Should not happen.
|
|
panic("cannot allocate node id: no free id found")
|
|
}
|
|
|
|
// Adds a node to the graph. Implementation note: if you add a node close to or at
|
|
// the max int on your machine NewNode will become slower.
|
|
func (g *DirectedGraph) AddNode(n graph.Node) {
|
|
if _, exists := g.nodeMap[n.ID()]; exists {
|
|
panic(fmt.Sprintf("concrete: node ID collision: %d", n.ID()))
|
|
}
|
|
g.nodeMap[n.ID()] = n
|
|
g.successors[n.ID()] = make(map[int]WeightedEdge)
|
|
g.predecessors[n.ID()] = make(map[int]WeightedEdge)
|
|
|
|
delete(g.freeMap, n.ID())
|
|
g.maxID = max(g.maxID, n.ID())
|
|
}
|
|
|
|
func (g *DirectedGraph) SetEdge(e graph.Edge, cost float64) {
|
|
var (
|
|
from = e.From()
|
|
fid = from.ID()
|
|
to = e.To()
|
|
tid = to.ID()
|
|
)
|
|
|
|
if fid == tid {
|
|
panic("concrete: adding self edge")
|
|
}
|
|
|
|
if !g.Has(from) {
|
|
g.AddNode(from)
|
|
}
|
|
|
|
if !g.Has(to) {
|
|
g.AddNode(to)
|
|
}
|
|
|
|
g.successors[fid][tid] = WeightedEdge{Edge: e, Cost: cost}
|
|
g.predecessors[tid][fid] = WeightedEdge{Edge: e, Cost: cost}
|
|
}
|
|
|
|
func (g *DirectedGraph) RemoveNode(n graph.Node) {
|
|
if _, ok := g.nodeMap[n.ID()]; !ok {
|
|
return
|
|
}
|
|
delete(g.nodeMap, n.ID())
|
|
|
|
for succ := range g.successors[n.ID()] {
|
|
delete(g.predecessors[succ], n.ID())
|
|
}
|
|
delete(g.successors, n.ID())
|
|
|
|
for pred := range g.predecessors[n.ID()] {
|
|
delete(g.successors[pred], n.ID())
|
|
}
|
|
delete(g.predecessors, n.ID())
|
|
|
|
g.maxID-- // Fun facts: even if this ID doesn't exist this still works!
|
|
g.freeMap[n.ID()] = struct{}{}
|
|
}
|
|
|
|
func (g *DirectedGraph) RemoveEdge(e graph.Edge) {
|
|
from, to := e.From(), e.To()
|
|
if _, ok := g.nodeMap[from.ID()]; !ok {
|
|
return
|
|
} else if _, ok := g.nodeMap[to.ID()]; !ok {
|
|
return
|
|
}
|
|
|
|
delete(g.successors[from.ID()], to.ID())
|
|
delete(g.predecessors[to.ID()], from.ID())
|
|
}
|
|
|
|
func (g *DirectedGraph) EmptyGraph() {
|
|
g.successors = make(map[int]map[int]WeightedEdge)
|
|
g.predecessors = make(map[int]map[int]WeightedEdge)
|
|
g.nodeMap = make(map[int]graph.Node)
|
|
}
|
|
|
|
/* Graph implementation */
|
|
|
|
func (g *DirectedGraph) From(n graph.Node) []graph.Node {
|
|
if _, ok := g.successors[n.ID()]; !ok {
|
|
return nil
|
|
}
|
|
|
|
successors := make([]graph.Node, len(g.successors[n.ID()]))
|
|
i := 0
|
|
for succ := range g.successors[n.ID()] {
|
|
successors[i] = g.nodeMap[succ]
|
|
i++
|
|
}
|
|
|
|
return successors
|
|
}
|
|
|
|
func (g *DirectedGraph) HasEdge(x, y graph.Node) bool {
|
|
xid := x.ID()
|
|
yid := y.ID()
|
|
if _, ok := g.nodeMap[xid]; !ok {
|
|
return false
|
|
}
|
|
if _, ok := g.nodeMap[yid]; !ok {
|
|
return false
|
|
}
|
|
if _, ok := g.successors[xid][yid]; ok {
|
|
return true
|
|
}
|
|
_, ok := g.successors[yid][xid]
|
|
return ok
|
|
}
|
|
|
|
func (g *DirectedGraph) Edge(u, v graph.Node) graph.Edge {
|
|
if _, ok := g.nodeMap[u.ID()]; !ok {
|
|
return nil
|
|
}
|
|
if _, ok := g.nodeMap[v.ID()]; !ok {
|
|
return nil
|
|
}
|
|
edge, ok := g.successors[u.ID()][v.ID()]
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return edge.Edge
|
|
}
|
|
|
|
func (g *DirectedGraph) HasEdgeFromTo(u, v graph.Node) bool {
|
|
if _, ok := g.nodeMap[u.ID()]; !ok {
|
|
return false
|
|
}
|
|
if _, ok := g.nodeMap[v.ID()]; !ok {
|
|
return false
|
|
}
|
|
if _, ok := g.successors[u.ID()][v.ID()]; !ok {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (g *DirectedGraph) To(n graph.Node) []graph.Node {
|
|
if _, ok := g.successors[n.ID()]; !ok {
|
|
return nil
|
|
}
|
|
|
|
predecessors := make([]graph.Node, len(g.predecessors[n.ID()]))
|
|
i := 0
|
|
for succ := range g.predecessors[n.ID()] {
|
|
predecessors[i] = g.nodeMap[succ]
|
|
i++
|
|
}
|
|
|
|
return predecessors
|
|
}
|
|
|
|
func (g *DirectedGraph) Node(id int) graph.Node {
|
|
return g.nodeMap[id]
|
|
}
|
|
|
|
func (g *DirectedGraph) Has(n graph.Node) bool {
|
|
_, ok := g.nodeMap[n.ID()]
|
|
|
|
return ok
|
|
}
|
|
|
|
func (g *DirectedGraph) Degree(n graph.Node) int {
|
|
if _, ok := g.nodeMap[n.ID()]; !ok {
|
|
return 0
|
|
}
|
|
|
|
return len(g.successors[n.ID()]) + len(g.predecessors[n.ID()])
|
|
}
|
|
|
|
func (g *DirectedGraph) Nodes() []graph.Node {
|
|
nodes := make([]graph.Node, len(g.successors))
|
|
i := 0
|
|
for _, n := range g.nodeMap {
|
|
nodes[i] = n
|
|
i++
|
|
}
|
|
|
|
return nodes
|
|
}
|
|
|
|
func (g *DirectedGraph) Weight(e graph.Edge) float64 {
|
|
if s, ok := g.successors[e.From().ID()]; ok {
|
|
if we, ok := s[e.To().ID()]; ok {
|
|
return we.Cost
|
|
}
|
|
}
|
|
return inf
|
|
}
|
|
|
|
func (g *DirectedGraph) Edges() []graph.Edge {
|
|
edgeList := make([]graph.Edge, 0, len(g.successors))
|
|
edgeMap := make(map[int]map[int]struct{}, len(g.successors))
|
|
for n, succMap := range g.successors {
|
|
edgeMap[n] = make(map[int]struct{}, len(succMap))
|
|
for succ, edge := range succMap {
|
|
if doneMap, ok := edgeMap[succ]; ok {
|
|
if _, ok := doneMap[n]; ok {
|
|
continue
|
|
}
|
|
}
|
|
edgeList = append(edgeList, edge)
|
|
edgeMap[n][succ] = struct{}{}
|
|
}
|
|
}
|
|
|
|
return edgeList
|
|
}
|