Skip to content

Commit

Permalink
Dag -> DAG
Browse files Browse the repository at this point in the history
  • Loading branch information
ValarDragon committed Apr 25, 2022
1 parent 24b8fd3 commit c9947b4
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 33 deletions.
46 changes: 23 additions & 23 deletions osmoutils/partialord/internal/dag/dag.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import (
"sort"
)

// Dag struct maintains a directed acyclic graph, using adjacency lists to track edges.
type Dag struct {
// DAG struct maintains a directed acyclic graph, using adjacency lists to track edges.
type DAG struct {
// there is a directed edge from u -> v, if directedEdgeList[u][v] = 1
// there is a directed edge from v -> u, if directedEdgeList[u][v] = -1
directedEdgeList []map[int]int8
nodeNameToId map[string]int
idToNodeNames map[int]string
}

func NewDag(nodes []string) Dag {
func NewDAG(nodes []string) DAG {
nodeNameToId := make(map[string]int, len(nodes))
idToNodeNames := make(map[int]string, len(nodes))
directedEdgeList := make([]map[int]int8, len(nodes))
Expand All @@ -26,7 +26,7 @@ func NewDag(nodes []string) Dag {
if len(nodeNameToId) != len(nodes) {
panic("provided multiple nodes with the same name")
}
return Dag{
return DAG{
directedEdgeList: directedEdgeList,
nodeNameToId: nodeNameToId,
idToNodeNames: idToNodeNames,
Expand All @@ -35,7 +35,7 @@ func NewDag(nodes []string) Dag {

// Copy returns a new dag struct that is a copy of the original dag.
// Edges can be mutated in the copy, without altering the original.
func (dag Dag) Copy() Dag {
func (dag DAG) Copy() DAG {
directedEdgeList := make([]map[int]int8, len(dag.nodeNameToId))
for i := 0; i < len(dag.nodeNameToId); i++ {
originalEdgeList := dag.directedEdgeList[i]
Expand All @@ -45,21 +45,21 @@ func (dag Dag) Copy() Dag {
}
}
// we re-use nodeNameToId and idToNodeNames as these are fixed at dag creation.
return Dag{
return DAG{
directedEdgeList: directedEdgeList,
nodeNameToId: dag.nodeNameToId,
idToNodeNames: dag.idToNodeNames,
}
}

func (dag Dag) hasDirectedEdge(u, v int) bool {
func (dag DAG) hasDirectedEdge(u, v int) bool {
uAdjacencyList := dag.directedEdgeList[u]
_, exists := uAdjacencyList[v]
return exists
}

// addEdge adds a directed edge from u -> v.
func (dag *Dag) addEdge(u, v int) error {
func (dag *DAG) addEdge(u, v int) error {
if u == v {
return fmt.Errorf("can't make self-edge")
}
Expand All @@ -73,7 +73,7 @@ func (dag *Dag) addEdge(u, v int) error {

// replaceEdge adds a directed edge from u -> v.
// it removes any edge that may already exist between the two.
func (dag *Dag) replaceEdge(u, v int) error {
func (dag *DAG) replaceEdge(u, v int) error {
if u == v {
return fmt.Errorf("can't make self-edge")
}
Expand All @@ -84,7 +84,7 @@ func (dag *Dag) replaceEdge(u, v int) error {
}

// resetEdges deletes all edges directed to or from node `u`
func (dag *Dag) resetEdges(u int) {
func (dag *DAG) resetEdges(u int) {
edges := dag.directedEdgeList[u]
for v := range edges {
delete(dag.directedEdgeList[v], u)
Expand All @@ -93,12 +93,12 @@ func (dag *Dag) resetEdges(u int) {
}

// deleteEdge deletes edges between u and v.
func (dag *Dag) deleteEdge(u, v int) {
func (dag *DAG) deleteEdge(u, v int) {
delete(dag.directedEdgeList[u], v)
delete(dag.directedEdgeList[v], u)
}

func (dag *Dag) AddEdge(u, v string) error {
func (dag *DAG) AddEdge(u, v string) error {
uIndex, uExists := dag.nodeNameToId[u]
vIndex, vExists := dag.nodeNameToId[v]
if !uExists || !vExists {
Expand All @@ -109,7 +109,7 @@ func (dag *Dag) AddEdge(u, v string) error {

// ReplaceEdge adds a directed edge from u -> v.
// it removes any edge that may already exist between the two.
func (dag *Dag) ReplaceEdge(u, v string) error {
func (dag *DAG) ReplaceEdge(u, v string) error {
uIndex, uExists := dag.nodeNameToId[u]
vIndex, vExists := dag.nodeNameToId[v]
if !uExists || !vExists {
Expand All @@ -121,7 +121,7 @@ func (dag *Dag) ReplaceEdge(u, v string) error {
// AddFirstElements sets the provided elements to be first in all orderings.
// So if were making an ordering over {A, B, C, D, E}, and elems provided is {D, B, A}
// then we are guaranteed that the total ordering will begin with {D, B, A}
func (dag *Dag) AddFirstElements(nodes ...string) error {
func (dag *DAG) AddFirstElements(nodes ...string) error {
nodeIds, err := dag.namesToIds(nodes)
if err != nil {
return err
Expand All @@ -130,7 +130,7 @@ func (dag *Dag) AddFirstElements(nodes ...string) error {
return dag.addFirst(nodeIds)
}

func (dag *Dag) addFirst(nodes []int) error {
func (dag *DAG) addFirst(nodes []int) error {
nodeMap := map[int]bool{}
for i := 0; i < len(nodes); i++ {
nodeMap[nodes[i]] = true
Expand Down Expand Up @@ -168,7 +168,7 @@ func (dag *Dag) addFirst(nodes []int) error {
// AddLastElements sets the provided elements to be last in all orderings.
// So if were making an ordering over {A, B, C, D, E}, and elems provided is {D, B, A}
// then we are guaranteed that the total ordering will end with {D, B, A}
func (dag *Dag) AddLastElements(nodes ...string) error {
func (dag *DAG) AddLastElements(nodes ...string) error {
nodeIds, err := dag.namesToIds(nodes)
if err != nil {
return err
Expand All @@ -177,7 +177,7 @@ func (dag *Dag) AddLastElements(nodes ...string) error {
return dag.addLast(nodeIds)
}

func (dag *Dag) addLast(nodes []int) error {
func (dag *DAG) addLast(nodes []int) error {
nodeMap := map[int]bool{}
for i := 0; i < len(nodes); i++ {
nodeMap[nodes[i]] = true
Expand Down Expand Up @@ -212,7 +212,7 @@ func (dag *Dag) addLast(nodes []int) error {
return nil
}

func (dag Dag) hasEdges() bool {
func (dag DAG) hasEdges() bool {
for _, m := range dag.directedEdgeList {
if len(m) > 0 {
return true
Expand All @@ -221,7 +221,7 @@ func (dag Dag) hasEdges() bool {
return false
}

func (dag *Dag) namesToIds(names []string) ([]int, error) {
func (dag *DAG) namesToIds(names []string) ([]int, error) {
nodeIds := []int{}
for _, name := range names {
nodeIndex, nodeExists := dag.nodeNameToId[name]
Expand All @@ -233,7 +233,7 @@ func (dag *Dag) namesToIds(names []string) ([]int, error) {
return nodeIds, nil
}

func (dag Dag) idsToNames(ids []int) []string {
func (dag DAG) idsToNames(ids []int) []string {
sortedNames := make([]string, 0, len(ids))
for i := 0; i < len(dag.nodeNameToId); i++ {
id := ids[i]
Expand All @@ -242,7 +242,7 @@ func (dag Dag) idsToNames(ids []int) []string {
return sortedNames
}

func (dag Dag) hasIncomingEdge(u int) bool {
func (dag DAG) hasIncomingEdge(u int) bool {
adjacencyList := dag.directedEdgeList[u]
for _, v := range adjacencyList {
if v == -1 {
Expand All @@ -253,7 +253,7 @@ func (dag Dag) hasIncomingEdge(u int) bool {
}

// returns nodes with no incoming edges.
func (dag *Dag) topologicalTopLevelNodes() []int {
func (dag *DAG) topologicalTopLevelNodes() []int {
topLevelNodes := []int{}

for i := 0; i < len(dag.nodeNameToId); i++ {
Expand All @@ -267,7 +267,7 @@ func (dag *Dag) topologicalTopLevelNodes() []int {

// Returns a Topological Sort of the DAG, using Kahn's algorithm.
// https://en.wikipedia.org/wiki/Topological_sorting#Kahn's_algorithm
func (dag Dag) TopologicalSort() []string {
func (dag DAG) TopologicalSort() []string {
// G is the mutable graph we work on, which we remove edges from.
G := dag.Copy()
// L in pseudocode
Expand Down
6 changes: 3 additions & 3 deletions osmoutils/partialord/internal/dag/dag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func TestTopologicalSort(t *testing.T) {
},
}
for _, tc := range tests {
dag := dag.NewDag(tc.nodes)
dag := dag.NewDAG(tc.nodes)
for _, edge := range tc.edges {
err := dag.AddEdge(edge.start, edge.end)
require.NoError(t, err)
Expand Down Expand Up @@ -95,7 +95,7 @@ func TestAddFirst(t *testing.T) {
},
}
for _, tc := range tests {
dag := dag.NewDag(tc.nodes)
dag := dag.NewDAG(tc.nodes)
dag.AddFirstElements(tc.first...)
for _, edge := range tc.replaceEdges {
err := dag.ReplaceEdge(edge.start, edge.end)
Expand Down Expand Up @@ -142,7 +142,7 @@ func TestAddLast(t *testing.T) {
},
}
for _, tc := range tests {
dag := dag.NewDag(tc.nodes)
dag := dag.NewDAG(tc.nodes)
dag.AddLastElements(tc.last...)
for _, edge := range tc.replaceEdges {
err := dag.ReplaceEdge(edge.start, edge.end)
Expand Down
14 changes: 7 additions & 7 deletions osmoutils/partialord/partialord.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
type PartialOrdering struct {
// underlying dag, the partial ordering is stored via a dag
// https://en.wikipedia.org/wiki/Topological_sorting#Relation_to_partial_orders
dag dag.Dag
dag dag.DAG
// bools for sealing, to prevent repeated invocation of first or last methods.
firstSealed bool
lastSealed bool
Expand All @@ -21,13 +21,13 @@ func NewPartialOrdering(elements []string) PartialOrdering {
copy(elementsCopy, elements)
sort.Strings(elementsCopy)
return PartialOrdering{
dag: dag.NewDag(elements),
dag: dag.NewDAG(elements),
firstSealed: false,
lastSealed: false,
}
}

func handleDagErr(err error) {
func handleDAGErr(err error) {
// all dag errors are logic errors that the intended users of this package should not make.
if err != nil {
panic(err)
Expand All @@ -38,14 +38,14 @@ func handleDagErr(err error) {
func (ord *PartialOrdering) After(A string, B string) {
// Set that A depends on B / an edge from B -> A
err := ord.dag.AddEdge(B, A)
handleDagErr(err)
handleDAGErr(err)
}

// After marks that A should come before B
func (ord *PartialOrdering) Before(A string, B string) {
// Set that B depends on A / an edge from A -> B
err := ord.dag.AddEdge(A, B)
handleDagErr(err)
handleDAGErr(err)
}

// Sets elems to be the first elements in the ordering.
Expand All @@ -58,7 +58,7 @@ func (ord *PartialOrdering) FirstElements(elems ...string) {
// We make every node in the dag have a dependency on elems[-1]
// then we change elems[-1] to depend on elems[-2], and so forth.
err := ord.dag.AddFirstElements(elems...)
handleDagErr(err)
handleDAGErr(err)
ord.firstSealed = true
}

Expand All @@ -72,7 +72,7 @@ func (ord *PartialOrdering) LastElements(elems ...string) {
// We make every node in the dag have a dependency on elems[0]
// then we make elems[1] depend on elems[0], and so forth.
err := ord.dag.AddLastElements(elems...)
handleDagErr(err)
handleDAGErr(err)
ord.lastSealed = true
}

Expand Down

0 comments on commit c9947b4

Please sign in to comment.