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
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
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
NodeList() []int // Returns a list of all node IDs in no particular order, useful for determining things like if a graph is fully connected
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. The caller is free to modify this list (so don't pass a reference to your own list)
IsDirected() bool
}
@@ -35,9 +35,9 @@ type HeuristicCoster interface {
// A Mutable Graph
type MutableGraph interface {
Graph
AddNode(id int, successors []int) // The graph itself is responsible for adding reciprocal edges if it's undirected
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
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)
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. 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) // 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
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
@@ -204,7 +204,7 @@ func FullyConnected(graph Graph) bool {
for _, node := range graph.NodeList() {
if deg := graph.Degree(node); deg == 0 {
return false
} else if deg == 2 {
} else if graph.Degree(node) == 2 {
if graph.Successors(node)[0] == node {
return false
}
@@ -254,7 +254,11 @@ func Prim(dst MutableGraph, graph Graph, Cost func(int, int) float64) {
sort.Sort(edgeWeights)
myEdge := edgeWeights[0]
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)
remainingNodes.Remove(myEdge.Edge[1])
@@ -292,7 +296,11 @@ func Kruskal(dst MutableGraph, graph Graph, Cost func(int, int) float64) {
for _, edge := range edgeWeights {
if s1, s2 := ds.Find(edge.Edge[0]), ds.Find(edge.Edge[1]); s1 != s2 {
ds.Union(s1, s2)
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)
}
}
@@ -339,7 +347,7 @@ func Dominators(start int, graph Graph) map[int]*Set {
dom.Add(node)
dom.Union(dom, tmp)
if !dom.Equal(dominators[node]) {
if !Equal(dom, dominators[node]) {
dominators[node] = dom
somethingChanged = true
}
@@ -388,7 +396,7 @@ func PostDominators(end int, graph Graph) map[int]*Set {
dom.Add(node)
dom.Union(dom, tmp)
if !dom.Equal(dominators[node]) {
if !Equal(dom, dominators[node]) {
dominators[node] = dom
somethingChanged = true
}

133
set.go
View File

@@ -49,7 +49,8 @@ func (dst *Set) Copy(src *Set) *Set {
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 {
return true
} else if len(*s1) != len(*s2) {
@@ -65,6 +66,15 @@ func (s1 *Set) Equal(s2 *Set) bool {
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 {
if s1 == s2 {
return dst.Copy(s1)
@@ -89,6 +99,19 @@ func (dst *Set) Union(s1, s2 *Set) *Set {
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 {
var swap *Set
@@ -122,13 +145,30 @@ func (dst *Set) Intersection(s1, s2 *Set) *Set {
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 {
if s1 == s2 {
return dst.Clear()
} else if s2 == dst {
tmp := NewSet()
return dst.Copy(tmp.Diff(s1, s2))
tmp.Diff(s1, s2)
*dst = *tmp
} else if s1 == dst {
for el := range *dst {
if _, ok := (*s2)[el]; ok {
@@ -148,25 +188,109 @@ func (dst *Set) Diff(s1, s2 *Set) *Set {
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 {
_, ok := (*s)[el]
return ok
}
// Are Add/Remove necessary?
// Adds the element el to s1
func (s1 *Set) Add(element interface{}) {
(*s1)[element] = flag
}
// Removes the element el from s1
func (s1 *Set) Remove(element interface{}) {
delete(*s1, element)
}
// Returns the number of elements in s1
func (s1 *Set) Cardinality() int {
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 */
// 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 {
master *Set
subsets []*Set
@@ -207,6 +331,9 @@ func (ds *DisjointSet) Find(el interface{}) *Set {
}
// 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) {
if s1 == s2 {
return