Skip to content

Commit

Permalink
Merge pull request #53 from dominikbraun/rename-permitcycles
Browse files Browse the repository at this point in the history
Rename `PermitCycles` to `PreventCycles`
  • Loading branch information
dominikbraun committed Oct 14, 2022
2 parents e75209c + bc4b043 commit 8e16f6c
Show file tree
Hide file tree
Showing 10 changed files with 30 additions and 29 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

### Changed
* Changed `AddVertex` to accept functional options.
* Renamed `PermitCycles` to `PreventCycles`. This seems to be the price to pay if English isn't a library author's native language.

### Fixed
* Fixed the behavior of `ShortestPath` when the target vertex is not reachable from one of the visited vertices.
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ fmt.Println(path)
![topological sort](img/topological-sort.svg)

```go
g := graph.New(graph.IntHash, graph.Directed(), graph.PermitCycles())
g := graph.New(graph.IntHash, graph.Directed(), graph.PreventCycles())

// Add vertices and edges ...

Expand All @@ -188,7 +188,7 @@ fmt.Println(order)
![transitive reduction](img/transitive-reduction.svg)

```go
g := graph.New(graph.StringHash, graph.Directed(), graph.PermitCycles())
g := graph.New(graph.StringHash, graph.Directed(), graph.PreventCycles())

// Add vertices and edges ...

Expand All @@ -200,7 +200,7 @@ _ := graph.TransitiveReduction(g)
![cycle checks](img/cycles.svg)

```go
g := graph.New(graph.IntHash, graph.PermitCycles())
g := graph.New(graph.IntHash, graph.PreventCycles())

g.AddVertex(1)
g.AddVertex(2)
Expand Down
6 changes: 3 additions & 3 deletions dag.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
// recursively and uses Kahn's algorithm.
func TopologicalSort[K comparable, T any](g Graph[K, T]) ([]K, error) {
if !isDAG(g) {
return nil, errors.New("topological sort can only be performed on DAGs created with the PermitCycles option")
return nil, errors.New("topological sort can only be performed on DAGs created with the PreventCycles option")
}

predecessorMap, err := g.PredecessorMap()
Expand Down Expand Up @@ -62,7 +62,7 @@ func TopologicalSort[K comparable, T any](g Graph[K, T]) ([]K, error) {
// With a time complexity of O(V(V+E)), TransitiveReduction is a very costly operation.
func TransitiveReduction[K comparable, T any](g Graph[K, T]) error {
if !isDAG(g) {
return errors.New("topological sort can only be performed on DAGs created with the PermitCycles option")
return errors.New("topological sort can only be performed on DAGs created with the PreventCycles option")
}

adjacencyMap, err := g.AdjacencyMap()
Expand Down Expand Up @@ -97,5 +97,5 @@ func TransitiveReduction[K comparable, T any](g Graph[K, T]) error {
}

func isDAG[K comparable, T any](g Graph[K, T]) bool {
return g.Traits().IsDirected && g.Traits().PermitCycles
return g.Traits().IsDirected && g.Traits().PreventCycles
}
4 changes: 2 additions & 2 deletions dag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func TestDirectedTopologicalSort(t *testing.T) {
}

for name, test := range tests {
graph := New(IntHash, Directed(), PermitCycles())
graph := New(IntHash, Directed(), PreventCycles())

for _, vertex := range test.vertices {
_ = graph.AddVertex(vertex)
Expand Down Expand Up @@ -108,7 +108,7 @@ func TestDirectedTransitiveReduction(t *testing.T) {
}

for name, test := range tests {
graph := New(StringHash, Directed(), PermitCycles())
graph := New(StringHash, Directed(), PreventCycles())

for _, vertex := range test.vertices {
_ = graph.AddVertex(vertex)
Expand Down
4 changes: 2 additions & 2 deletions directed.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ func (d *directed[K, T]) AddEdge(sourceHash, targetHash K, options ...func(*Edge
return fmt.Errorf("an edge between vertices %v and %v already exists", sourceHash, targetHash)
}

// If the user opted in to permitting cycles, run a cycle check.
if d.traits.PermitCycles {
// If the user opted in to preventing cycles, run a cycle check.
if d.traits.PreventCycles {
createsCycle, err := CreatesCycle[K, T](d, sourceHash, targetHash)
if err != nil {
return fmt.Errorf("failed to check for cycles: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion directed_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func TestDirected_AddEdge(t *testing.T) {
{Source: 3, Target: 1},
},
traits: &Traits{
PermitCycles: true,
PreventCycles: true,
},
shouldFinallyFail: true,
},
Expand Down
18 changes: 9 additions & 9 deletions traits.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ package graph
//
// This will set the IsDirected field to true.
type Traits struct {
IsDirected bool
IsAcyclic bool
IsWeighted bool
IsRooted bool
PermitCycles bool
IsDirected bool
IsAcyclic bool
IsWeighted bool
IsRooted bool
PreventCycles bool
}

// Directed creates a directed graph. This has implications on graph traversal and the order of
Expand All @@ -24,7 +24,7 @@ func Directed() func(*Traits) {
}

// Acyclic creates an acyclic graph. Note that creating edges that form a cycle will still be
// possible. To prevent this explicitly, use PermitCycles.
// possible. To prevent this explicitly, use PreventCycles.
func Acyclic() func(*Traits) {
return func(t *Traits) {
t.IsAcyclic = true
Expand Down Expand Up @@ -53,11 +53,11 @@ func Tree() func(*Traits) {
}
}

// PermitCycles creates an acyclic graph that permits and proactively prevents the creation of
// PreventCycles creates an acyclic graph that prevents and proactively prevents the creation of
// cycles. These cycle checks affect the performance and complexity of operations such as AddEdge.
func PermitCycles() func(*Traits) {
func PreventCycles() func(*Traits) {
return func(t *Traits) {
Acyclic()(t)
t.PermitCycles = true
t.PreventCycles = true
}
}
12 changes: 6 additions & 6 deletions traits_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,22 +113,22 @@ func TestTree(t *testing.T) {
}
}

func TestPermitCycles(t *testing.T) {
func TestPreventCycles(t *testing.T) {
tests := map[string]struct {
expected *Traits
}{
"permit cycles": {
"prevent cycles": {
expected: &Traits{
IsAcyclic: true,
PermitCycles: true,
IsAcyclic: true,
PreventCycles: true,
},
},
}

for name, test := range tests {
p := &Traits{}

PermitCycles()(p)
PreventCycles()(p)

if !traitsAreEqual(test.expected, p) {
t.Errorf("%s: trait expectation doesn't match: expected %v, got %v", name, test.expected, p)
Expand All @@ -141,5 +141,5 @@ func traitsAreEqual(a, b *Traits) bool {
a.IsDirected == b.IsDirected &&
a.IsRooted == b.IsRooted &&
a.IsWeighted == b.IsWeighted &&
a.PermitCycles == b.PermitCycles
a.PreventCycles == b.PreventCycles
}
4 changes: 2 additions & 2 deletions undirected.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ func (u *undirected[K, T]) AddEdge(sourceHash, targetHash K, options ...func(*Ed
return fmt.Errorf("an edge between vertices %v and %v already exists", sourceHash, targetHash)
}

// If the user opted in to permitting cycles, run a cycle check.
if u.traits.PermitCycles {
// If the user opted in to preventing cycles, run a cycle check.
if u.traits.PreventCycles {
createsCycle, err := CreatesCycle[K, T](u, sourceHash, targetHash)
if err != nil {
return fmt.Errorf("failed to check for cycles: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion undirected_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ func TestUndirected_AddEdge(t *testing.T) {
vertices: []int{1, 2, 3},
edgeHashes: [][3]int{{1, 2, 0}, {2, 3, 0}, {3, 1, 0}},
traits: &Traits{
PermitCycles: true,
PreventCycles: true,
},
shouldFinallyFail: true,
},
Expand Down

0 comments on commit 8e16f6c

Please sign in to comment.