From d15e23cf1348062f5d3cfdd79aefba39000bf611 Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Mon, 2 Aug 2021 13:37:13 +0200 Subject: [PATCH] Implicitly add vertices when adding edges to a DAG --- abc/dag/sorteddag.nim | 22 +++++++++++----------- tests/abc/testSortedDag.nim | 31 +++---------------------------- 2 files changed, 14 insertions(+), 39 deletions(-) diff --git a/abc/dag/sorteddag.nim b/abc/dag/sorteddag.nim index 1a9ad70..48ec634 100644 --- a/abc/dag/sorteddag.nim +++ b/abc/dag/sorteddag.nim @@ -25,6 +25,12 @@ type func new*[V](_: type SortedDag[V]): SortedDag[V] = SortedDag[V]() +func contains*[V](dag: SortedDag[V], vertex: V): bool = + vertex in dag.order + +func contains*[V](dag: SortedDag[V], edge: Edge[V]): bool = + edge in dag.edges + func lookup[V](dag: SortedDag[V], vertex: V): SortedVertex[V] = SortedVertex[V](vertex: vertex, index: dag.order[vertex]) @@ -82,23 +88,17 @@ func update[V](dag: SortedDag[V], lowerbound, upperbound: SortedVertex[V]) = let backward = searchBackward(dag, upperbound, lowerbound) dag.reorder(forward, backward) -func add*[V](dag: SortedDag[V], vertex: V) = - ## Adds a vertex to the DAG - dag.order[vertex] = -(dag.order.len) +func add[V](dag: SortedDag[V], vertex: V) = + if vertex notin dag: + dag.order[vertex] = -(dag.order.len) func add*[V](dag: SortedDag[V], edge: tuple[x, y: V]) = ## Adds an edge x -> y to the DAG - doAssert edge.x in dag - doAssert edge.y in dag + dag.add(edge.y) + dag.add(edge.x) dag.edges.incl(edge) dag.update(dag.lookup(edge.y), dag.lookup(edge.x)) -func contains*[V](dag: SortedDag[V], vertex: V): bool = - vertex in dag.order - -func contains*[V](dag: SortedDag[V], edge: Edge[V]): bool = - edge in dag.edges - iterator visit*[V](dag: SortedDag[V], start: V): V = ## Visits all vertices that are reachable from the starting vertex. Vertices ## are visited in topological order, meaning that vertices close to the diff --git a/tests/abc/testSortedDag.nim b/tests/abc/testSortedDag.nim index 632a4c2..0d7582d 100644 --- a/tests/abc/testSortedDag.nim +++ b/tests/abc/testSortedDag.nim @@ -8,31 +8,21 @@ suite "Sorted DAG": test "contains vertices": var dag = SortedDag[int].new - dag.add(1) + dag.add( (1, 2) ) check 1 in dag + check 2 in dag check 42 notin dag - dag.add(42) + dag.add( (2, 42) ) check 42 in dag test "contains edges": var dag = SortedDag[int].new - dag.add(1) - dag.add(2) - dag.add(3) dag.add( (1, 2) ) check (1, 2) in dag check (2, 3) notin dag dag.add( (2, 3) ) check (2, 3) in dag - test "raises when adding adding edge for unknown vertex": - var dag = SortedDag[int].new - dag.add(1) - expect Defect: - dag.add( (1, 2) ) - expect Defect: - dag.add( (2, 1) ) - test "visits reachable vertices, nearest first": # ⓪ → ① @@ -40,8 +30,6 @@ suite "Sorted DAG": # ② var dag = SortedDag[int].new - for vertex in 0..2: - dag.add(vertex) for edge in [ (0, 1), (1, 2), (0, 2) ]: dag.add(edge) @@ -58,8 +46,6 @@ suite "Sorted DAG": # ③ var dag = SortedDag[int].new - for vertex in 0..5: - dag.add(vertex) for edge in [ (5, 2), (5, 0), (4, 0), (4, 1), (2, 3), (3, 1) ]: dag.add(edge) @@ -79,8 +65,6 @@ suite "Sorted DAG": # gain ← spend var dag = SortedDag[string].new - for vertex in ["spend", "gain", "ack1", "ack2", "acks"]: - dag.add(vertex) for edge in [("acks", "ack1"), ("acks", "ack2"), ("ack1", "gain"), @@ -106,8 +90,6 @@ suite "Sorted DAG": # ⑤ → ⑩ var dag = SortedDag[int].new - for vertex in 0..10: - dag.add(vertex) for vertex in [1,6]: dag.add((0, vertex)) for vertex in 1..<5: @@ -126,11 +108,6 @@ suite "Sorted DAG": var dag = SortedDag[int].new var vertices: seq[int] - for vertex in 0..100: - vertices.add(vertex) - vertices.shuffle() - for vertex in vertices: - dag.add(vertex) for _ in 0..10_000: let x, y = rand(100) @@ -147,9 +124,7 @@ suite "Sorted DAG": # ⓪ ← ① ← ② ← ... var dag = SortedDag[int].new - dag.add(0) for i in 1..10_000: - dag.add(i) dag.add((i, i-1)) var latest = 10_000