Minor changes, TileGraph skeleton

This commit is contained in:
Jsor
2013-07-24 02:41:07 -07:00
parent 637ff7deeb
commit ddc8ab1944
2 changed files with 152 additions and 17 deletions

View File

@@ -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
View File

@@ -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