mirror of
https://github.com/gonum/gonum.git
synced 2025-10-11 01:50:12 +08:00
Minor changes, TileGraph skeleton
This commit is contained in:
36
graph.go
36
graph.go
@@ -13,8 +13,8 @@ type Graph interface {
|
|||||||
IsAdjacent(node, neighbor int) bool // IsSuccessor || IsPredecessor
|
IsAdjacent(node, neighbor int) bool // IsSuccessor || IsPredecessor
|
||||||
NodeExists(node int) bool // Returns whether a node with the given ID is currently in the graph
|
NodeExists(node int) bool // Returns whether a node with the given ID is currently in the graph
|
||||||
Degree(node int) int // Degree is equivalent to len(Successors(node)) + len(Predecessors(node)); this means that reflexive edges are counted twice
|
Degree(node int) int // Degree is equivalent to len(Successors(node)) + len(Predecessors(node)); this means that reflexive edges are counted twice
|
||||||
EdgeList() [][2]int // Returns a list of all edges in the graph. In the case of an directed graph edge[0] goes TO edge[1]. In an undirected graph you do only need provide one direction
|
EdgeList() [][2]int // Returns a list of all edges in the graph. In the case of an directed graph edge[0] goes TO edge[1]. In an undirected graph you do only need provide one direction (but may provide both)
|
||||||
NodeList() []int // Returns a list of all node IDs in no particular order, useful for determining things like if a graph is fully connected
|
NodeList() []int // Returns a list of all node IDs in no particular order, useful for determining things like if a graph is fully connected. The caller is free to modify this list (so don't pass a reference to your own list)
|
||||||
IsDirected() bool
|
IsDirected() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,13 +35,13 @@ type HeuristicCoster interface {
|
|||||||
// A Mutable Graph
|
// A Mutable Graph
|
||||||
type MutableGraph interface {
|
type MutableGraph interface {
|
||||||
Graph
|
Graph
|
||||||
AddNode(id int, successors []int) // The graph itself is responsible for adding reciprocal edges if it's undirected
|
AddNode(id int, successors []int) // The graph itself is responsible for adding reciprocal edges if it's undirected. Likewise, the graph itself must add any non-existant edges listed in successors.
|
||||||
AddEdge(node1, node2 int) // For a digraph, adds node1->node2; the graph is free to initialize this to any value it wishes. An error should be returned if the edge has not been initialized with AddEdge
|
AddEdge(node1, node2 int) // For a digraph, adds node1->node2; the graph is free to initialize this to any value it wishes. Node1 must exist, or it will result in undefined behavior, node2 must be created by the function if absent
|
||||||
SetEdgeCost(node1, node2 int, cost float64) error // Returns an error if the edge has not been created with AddEdge (or the edge was removed before this function was called)
|
SetEdgeCost(node1, node2 int, cost float64) // The behavior is undefined if the edge has not been created with AddEdge (or the edge was removed before this function was called). For a directed graph only sets node1->node2
|
||||||
RemoveNode(node int) // The graph is reponsible for removing edges to a node that is removed
|
RemoveNode(node int) // The graph is reponsible for removing edges to a node that is removed
|
||||||
RemoveEdge(node1, node2 int) // The graph is responsible for removing reciprocal edges if it's undirected
|
RemoveEdge(node1, node2 int) // The graph is responsible for removing reciprocal edges if it's undirected
|
||||||
EmptyGraph() // Clears the graph of all nodes and edges
|
EmptyGraph() // Clears the graph of all nodes and edges
|
||||||
SetDirected(bool) // This package will only call SetDirected on an empty graph, so there's no need to worry about the case where a graph suddenly becomes (un)directed
|
SetDirected(bool) // This package will only call SetDirected on an empty graph, so there's no need to worry about the case where a graph suddenly becomes (un)directed
|
||||||
}
|
}
|
||||||
|
|
||||||
// A package that contains an edge (as from EdgeList), and a Weight (as if Cost(Edge[0], Edge[1]) had been called)
|
// A package that contains an edge (as from EdgeList), and a Weight (as if Cost(Edge[0], Edge[1]) had been called)
|
||||||
@@ -204,7 +204,7 @@ func FullyConnected(graph Graph) bool {
|
|||||||
for _, node := range graph.NodeList() {
|
for _, node := range graph.NodeList() {
|
||||||
if deg := graph.Degree(node); deg == 0 {
|
if deg := graph.Degree(node); deg == 0 {
|
||||||
return false
|
return false
|
||||||
} else if deg == 2 {
|
} else if graph.Degree(node) == 2 {
|
||||||
if graph.Successors(node)[0] == node {
|
if graph.Successors(node)[0] == node {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -254,7 +254,11 @@ func Prim(dst MutableGraph, graph Graph, Cost func(int, int) float64) {
|
|||||||
sort.Sort(edgeWeights)
|
sort.Sort(edgeWeights)
|
||||||
myEdge := edgeWeights[0]
|
myEdge := edgeWeights[0]
|
||||||
|
|
||||||
dst.AddNode(myEdge.Edge[0], []int{myEdge.Edge[1]})
|
if !dst.NodeExists(myEdge.Edge[0]) {
|
||||||
|
dst.AddNode(myEdge.Edge[0], []int{myEdge.Edge[1]})
|
||||||
|
} else {
|
||||||
|
dst.AddEdge(myEdge.Edge[0], myEdge.Edge[1])
|
||||||
|
}
|
||||||
dst.SetEdgeCost(myEdge.Edge[0], myEdge.Edge[1], myEdge.Weight)
|
dst.SetEdgeCost(myEdge.Edge[0], myEdge.Edge[1], myEdge.Weight)
|
||||||
|
|
||||||
remainingNodes.Remove(myEdge.Edge[1])
|
remainingNodes.Remove(myEdge.Edge[1])
|
||||||
@@ -292,7 +296,11 @@ func Kruskal(dst MutableGraph, graph Graph, Cost func(int, int) float64) {
|
|||||||
for _, edge := range edgeWeights {
|
for _, edge := range edgeWeights {
|
||||||
if s1, s2 := ds.Find(edge.Edge[0]), ds.Find(edge.Edge[1]); s1 != s2 {
|
if s1, s2 := ds.Find(edge.Edge[0]), ds.Find(edge.Edge[1]); s1 != s2 {
|
||||||
ds.Union(s1, s2)
|
ds.Union(s1, s2)
|
||||||
dst.AddNode(edge.Edge[0], []int{edge.Edge[1]})
|
if !dst.NodeExists(edge.Edge[0]) {
|
||||||
|
dst.AddNode(edge.Edge[0], []int{edge.Edge[1]})
|
||||||
|
} else {
|
||||||
|
dst.AddEdge(edge.Edge[0], edge.Edge[1])
|
||||||
|
}
|
||||||
dst.SetEdgeCost(edge.Edge[0], edge.Edge[1], edge.Weight)
|
dst.SetEdgeCost(edge.Edge[0], edge.Edge[1], edge.Weight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -339,7 +347,7 @@ func Dominators(start int, graph Graph) map[int]*Set {
|
|||||||
dom.Add(node)
|
dom.Add(node)
|
||||||
|
|
||||||
dom.Union(dom, tmp)
|
dom.Union(dom, tmp)
|
||||||
if !dom.Equal(dominators[node]) {
|
if !Equal(dom, dominators[node]) {
|
||||||
dominators[node] = dom
|
dominators[node] = dom
|
||||||
somethingChanged = true
|
somethingChanged = true
|
||||||
}
|
}
|
||||||
@@ -388,7 +396,7 @@ func PostDominators(end int, graph Graph) map[int]*Set {
|
|||||||
dom.Add(node)
|
dom.Add(node)
|
||||||
|
|
||||||
dom.Union(dom, tmp)
|
dom.Union(dom, tmp)
|
||||||
if !dom.Equal(dominators[node]) {
|
if !Equal(dom, dominators[node]) {
|
||||||
dominators[node] = dom
|
dominators[node] = dom
|
||||||
somethingChanged = true
|
somethingChanged = true
|
||||||
}
|
}
|
||||||
|
133
set.go
133
set.go
@@ -49,7 +49,8 @@ func (dst *Set) Copy(src *Set) *Set {
|
|||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s1 *Set) Equal(s2 *Set) bool {
|
// If every element in s1 is also in s2 (and vice versa), the sets are deemed equal
|
||||||
|
func Equal(s1, s2 *Set) bool {
|
||||||
if s1 == s2 {
|
if s1 == s2 {
|
||||||
return true
|
return true
|
||||||
} else if len(*s1) != len(*s2) {
|
} else if len(*s1) != len(*s2) {
|
||||||
@@ -65,6 +66,15 @@ func (s1 *Set) Equal(s2 *Set) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Takes the union of s1 and s2, and stores it in dst.
|
||||||
|
//
|
||||||
|
// The union of two sets, s1 and s2, is the set containing all the elements of each, for instance:
|
||||||
|
//
|
||||||
|
// {a,b,c} UNION {d,e,f} = {a,b,c,d,e,f}
|
||||||
|
//
|
||||||
|
// Since sets may not have repetition, unions of two sets that overlap do not contain repeat elements, that is:
|
||||||
|
//
|
||||||
|
// {a,b,c} UNION {b,c,d} = {a,b,c,d}
|
||||||
func (dst *Set) Union(s1, s2 *Set) *Set {
|
func (dst *Set) Union(s1, s2 *Set) *Set {
|
||||||
if s1 == s2 {
|
if s1 == s2 {
|
||||||
return dst.Copy(s1)
|
return dst.Copy(s1)
|
||||||
@@ -89,6 +99,19 @@ func (dst *Set) Union(s1, s2 *Set) *Set {
|
|||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Takes the intersection of s1 and s2, and stores it in dst
|
||||||
|
//
|
||||||
|
// The intersection of two sets, s1 and s2, is the set containing all the elements shared between the two sets, for instance
|
||||||
|
//
|
||||||
|
// {a,b,c} INTERSECT {b,c,d} = {b,c}
|
||||||
|
//
|
||||||
|
// The intersection between a set and itself is itself, and thus effectively a copy operation:
|
||||||
|
//
|
||||||
|
// {a,b,c} INTERSECT {a,b,c} = {a,b,c}
|
||||||
|
//
|
||||||
|
// The intersection between two sets that share no elements is the empty set:
|
||||||
|
//
|
||||||
|
// {a,b,c} INTERSECT {d,e,f} = {}
|
||||||
func (dst *Set) Intersection(s1, s2 *Set) *Set {
|
func (dst *Set) Intersection(s1, s2 *Set) *Set {
|
||||||
var swap *Set
|
var swap *Set
|
||||||
|
|
||||||
@@ -122,13 +145,30 @@ func (dst *Set) Intersection(s1, s2 *Set) *Set {
|
|||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Takes the difference (-) of s1 and s2 and stores it in dst.
|
||||||
|
//
|
||||||
|
// The difference (-) between two sets, s1 and s2, is all the elements in s1 that are NOT also in s2.
|
||||||
|
//
|
||||||
|
// {a,b,c} - {b,c,d} = {a}
|
||||||
|
//
|
||||||
|
// The difference between two identical sets is the empty set:
|
||||||
|
//
|
||||||
|
// {a,b,c} - {a,b,c} = {a}
|
||||||
|
//
|
||||||
|
// The difference between two sets with no overlapping elements is s1
|
||||||
|
//
|
||||||
|
// {a,b,c} - {d,e,f} = {a,b,c}
|
||||||
|
//
|
||||||
|
// Implementation note: if dst == s2 (meaning they have identical pointers), a temporary set must be used to store the data
|
||||||
|
// and then copied over, thus s2.Diff(s1,s2) has an extra allocation and may cause worse performance in some cases.
|
||||||
func (dst *Set) Diff(s1, s2 *Set) *Set {
|
func (dst *Set) Diff(s1, s2 *Set) *Set {
|
||||||
if s1 == s2 {
|
if s1 == s2 {
|
||||||
return dst.Clear()
|
return dst.Clear()
|
||||||
} else if s2 == dst {
|
} else if s2 == dst {
|
||||||
tmp := NewSet()
|
tmp := NewSet()
|
||||||
|
|
||||||
return dst.Copy(tmp.Diff(s1, s2))
|
tmp.Diff(s1, s2)
|
||||||
|
*dst = *tmp
|
||||||
} else if s1 == dst {
|
} else if s1 == dst {
|
||||||
for el := range *dst {
|
for el := range *dst {
|
||||||
if _, ok := (*s2)[el]; ok {
|
if _, ok := (*s2)[el]; ok {
|
||||||
@@ -148,25 +188,109 @@ func (dst *Set) Diff(s1, s2 *Set) *Set {
|
|||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true if s1 is an improper subset of s2.
|
||||||
|
//
|
||||||
|
// An improper subset occurs when every element in s1 is also in s2 OR s1 and s2 are equal:
|
||||||
|
//
|
||||||
|
// {a,b,c} SUBSET {a,b,c} = true
|
||||||
|
// {a,b} SUBSET {a,b,c} = true
|
||||||
|
// {c,d} SUBSET {a,b,c} = false
|
||||||
|
// {a,b,c,d} SUBSET {a,b,c} = false
|
||||||
|
//
|
||||||
|
// Special case: The empty set is a subset of everything
|
||||||
|
//
|
||||||
|
// {} SUBSET {a,b} = true
|
||||||
|
// {} SUBSET {} = true
|
||||||
|
//
|
||||||
|
// In the case where one needs to test if s1 is smaller than s2, but not equal, use ProperSubset
|
||||||
|
func Subset(s1, s2 *Set) bool {
|
||||||
|
if len(*s1) > len(*s2) {
|
||||||
|
return false
|
||||||
|
} else if s1 == s2 {
|
||||||
|
return true
|
||||||
|
} else if len(*s1) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, el := range *s1 {
|
||||||
|
if _, ok := (*s2)[el]; !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if s1 is a proper subset of s2.
|
||||||
|
// A proper subset is when every element of s1 is in s2, but s1 is smaller than s2 (i.e. they are not equal):
|
||||||
|
//
|
||||||
|
// {a,b,c} PROPER SUBSET {a,b,c} = false
|
||||||
|
// {a,b} PROPER SUBSET {a,b,c} = true
|
||||||
|
// {c,d} PROPER SUBSET {a,b,c} = false
|
||||||
|
// {a,b,c,d} PROPER SUBSET {a,b,c} = false
|
||||||
|
//
|
||||||
|
// Special case: The empty set is a proper subset of everything (except itself):
|
||||||
|
//
|
||||||
|
// {} PROPER SUBSET {a,b} = true
|
||||||
|
// {} PROPER SUBSET {} = false
|
||||||
|
//
|
||||||
|
// When equality is allowed, use Subset
|
||||||
|
func ProperSubset(s1, s2 *Set) bool {
|
||||||
|
if len(*s1) >= len(*s2) {
|
||||||
|
return false
|
||||||
|
} else if len(*s1) == 0 {
|
||||||
|
return true
|
||||||
|
} // We can eschew the s1 == s2 because if they are the same their lens are equal anyway
|
||||||
|
|
||||||
|
for _, el := range *s1 {
|
||||||
|
if _, ok := (*s2)[el]; !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if el is an element of s.
|
||||||
func (s *Set) Contains(el interface{}) bool {
|
func (s *Set) Contains(el interface{}) bool {
|
||||||
_, ok := (*s)[el]
|
_, ok := (*s)[el]
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are Add/Remove necessary?
|
// Adds the element el to s1
|
||||||
func (s1 *Set) Add(element interface{}) {
|
func (s1 *Set) Add(element interface{}) {
|
||||||
(*s1)[element] = flag
|
(*s1)[element] = flag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Removes the element el from s1
|
||||||
func (s1 *Set) Remove(element interface{}) {
|
func (s1 *Set) Remove(element interface{}) {
|
||||||
delete(*s1, element)
|
delete(*s1, element)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the number of elements in s1
|
||||||
func (s1 *Set) Cardinality() int {
|
func (s1 *Set) Cardinality() int {
|
||||||
return len(*s1)
|
return len(*s1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s1 *Set) Elements() (els []interface{}) {
|
||||||
|
els = make([]interface{}, 0, len(*s1))
|
||||||
|
for _, el := range *s1 {
|
||||||
|
els = append(els, el)
|
||||||
|
}
|
||||||
|
|
||||||
|
return els
|
||||||
|
}
|
||||||
|
|
||||||
/* Should probably be re-implemented as a tree later */
|
/* Should probably be re-implemented as a tree later */
|
||||||
|
|
||||||
|
// A disjoint set is a collection of non-overlapping sets. That is, for any two sets in the disjoint set, their intersection is the empty set
|
||||||
|
//
|
||||||
|
// A disjoint set has three principle operations: Make Set, Find, and Union.
|
||||||
|
//
|
||||||
|
// Make set creates a new set for an element (presuming it does not already exist in any set in the disjoint set), Find finds the set containing that element (if any),
|
||||||
|
// and Union merges two sets in the disjoint set. In general, algorithms operating on disjoint sets are "union-find" algorithms, where two sets are found with Find, and then joined with Union.
|
||||||
|
//
|
||||||
|
// A concrete example of a union-find algorithm can be found as discrete.Kruskal -- which unions two sets when an edge is created between two vertices, and refuses to make an edge between two vertices if they're part of the same set.
|
||||||
type DisjointSet struct {
|
type DisjointSet struct {
|
||||||
master *Set
|
master *Set
|
||||||
subsets []*Set
|
subsets []*Set
|
||||||
@@ -207,6 +331,9 @@ func (ds *DisjointSet) Find(el interface{}) *Set {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unions two subsets within the DisjointSet
|
// Unions two subsets within the DisjointSet
|
||||||
|
//
|
||||||
|
// If either s1 or s2 do not appear in the disjoint set (meaning their pointers, deep equality is not tested),
|
||||||
|
// the function will return without doing anything. Finding sets to perform a union on is typically done with Find.
|
||||||
func (ds *DisjointSet) Union(s1, s2 *Set) {
|
func (ds *DisjointSet) Union(s1, s2 *Set) {
|
||||||
if s1 == s2 {
|
if s1 == s2 {
|
||||||
return
|
return
|
||||||
|
Reference in New Issue
Block a user