mirror of https://github.com/status-im/nim-abc.git
Create edges using -> operator, to make direction of edge explicit
This commit is contained in:
parent
d15e23cf13
commit
0a604491ee
|
@ -6,18 +6,18 @@ type
|
|||
# invariant: (∀ x->y ∈ outgoing: y<-x ∈ incoming)
|
||||
outgoing: Table[Vertex, HashSet[Vertex]]
|
||||
incoming: Table[Vertex, HashSet[Vertex]]
|
||||
Edge*[Vertex] = (Vertex, Vertex)
|
||||
Edge*[Vertex] = object
|
||||
x*, y* : Vertex
|
||||
|
||||
func init*[V](_: type EdgeSet[V]): EdgeSet[V] =
|
||||
discard
|
||||
|
||||
func incl*[V](edges: var EdgeSet[V], edge: Edge[V]) =
|
||||
let (x, y) = edge
|
||||
edges.outgoing.mgetOrPut(x, HashSet[V].default).incl(y)
|
||||
edges.incoming.mgetOrPut(y, HashSet[V].default).incl(x)
|
||||
edges.outgoing.mgetOrPut(edge.x, HashSet[V].default).incl(edge.y)
|
||||
edges.incoming.mgetOrPut(edge.y, HashSet[V].default).incl(edge.x)
|
||||
|
||||
func contains*[V](edges: EdgeSet[V], edge: Edge[V]): bool =
|
||||
edge[1] in edges.outgoing.getOrDefault(edge[0])
|
||||
edge.y in edges.outgoing.getOrDefault(edge.x)
|
||||
|
||||
iterator outgoing*[V](edges: EdgeSet[V], vertex: V): V =
|
||||
for v in edges.outgoing.getOrDefault(vertex).items:
|
||||
|
@ -26,3 +26,6 @@ iterator outgoing*[V](edges: EdgeSet[V], vertex: V): V =
|
|||
iterator incoming*[V](edges: EdgeSet[V], vertex: V): V =
|
||||
for v in edges.incoming.getOrDefault(vertex).items:
|
||||
yield v
|
||||
|
||||
func `->`*[V](x, y: V): Edge[V] =
|
||||
Edge[V](x: x, y: y)
|
||||
|
|
|
@ -13,6 +13,8 @@ import ./merge
|
|||
## Uses the dynamic topological sort algorithm by
|
||||
## [Pearce and Kelly](https://www.doc.ic.ac.uk/~phjk/Publications/DynamicTopoSortAlg-JEA-07.pdf).
|
||||
|
||||
export `->`
|
||||
|
||||
type
|
||||
SortedDag*[Vertex] = ref object
|
||||
## A DAG whose vertices are kept in topological order
|
||||
|
@ -92,7 +94,7 @@ 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]) =
|
||||
func add*[V](dag: SortedDag[V], edge: Edge[V]) =
|
||||
## Adds an edge x -> y to the DAG
|
||||
dag.add(edge.y)
|
||||
dag.add(edge.x)
|
||||
|
|
|
@ -11,15 +11,15 @@ suite "DAG edge set":
|
|||
edges = EdgeSet[string].init()
|
||||
|
||||
test "contains edges":
|
||||
edges.incl( ("a", "b") )
|
||||
check ("a", "b") in edges
|
||||
check not ( ("a", "c") in edges )
|
||||
check not ( ("b", "a") in edges )
|
||||
edges.incl("a"->"b")
|
||||
check ("a"->"b") in edges
|
||||
check ("a"->"c") notin edges
|
||||
check ("b"->"a") notin edges
|
||||
|
||||
test "iterates over outgoing edges":
|
||||
edges.incl( ("a", "b") )
|
||||
edges.incl( ("b", "c") )
|
||||
edges.incl( ("a", "c") )
|
||||
edges.incl("a"->"b")
|
||||
edges.incl("b"->"c")
|
||||
edges.incl("a"->"c")
|
||||
let neighboursA = toSeq(edges.outgoing("a"))
|
||||
let neighboursB = toSeq(edges.outgoing("b"))
|
||||
let neighboursC = toSeq(edges.outgoing("c"))
|
||||
|
@ -30,9 +30,9 @@ suite "DAG edge set":
|
|||
check "c" in neighboursB
|
||||
|
||||
test "iterates over incoming edges":
|
||||
edges.incl( ("a", "b") )
|
||||
edges.incl( ("b", "c") )
|
||||
edges.incl( ("a", "c") )
|
||||
edges.incl("a"->"b")
|
||||
edges.incl("b"->"c")
|
||||
edges.incl("a"->"c")
|
||||
let neighboursA = toSeq(edges.incoming("a"))
|
||||
let neighboursB = toSeq(edges.incoming("b"))
|
||||
let neighboursC = toSeq(edges.incoming("c"))
|
||||
|
@ -48,7 +48,7 @@ suite "DAG edge set":
|
|||
let x, y = rand(100)
|
||||
if x != y:
|
||||
let (x, y) = (min(x,y), max(x,y))
|
||||
large.incl((x,y))
|
||||
check (x, y) in large
|
||||
large.incl(x->y)
|
||||
check (x->y) in large
|
||||
check y in toSeq large.outgoing(x)
|
||||
check x in toSeq large.incoming(y)
|
||||
|
|
|
@ -8,20 +8,20 @@ suite "Sorted DAG":
|
|||
|
||||
test "contains vertices":
|
||||
var dag = SortedDag[int].new
|
||||
dag.add( (1, 2) )
|
||||
dag.add(1->2)
|
||||
check 1 in dag
|
||||
check 2 in dag
|
||||
check 42 notin dag
|
||||
dag.add( (2, 42) )
|
||||
dag.add(2->42)
|
||||
check 42 in dag
|
||||
|
||||
test "contains edges":
|
||||
var dag = SortedDag[int].new
|
||||
dag.add( (1, 2) )
|
||||
check (1, 2) in dag
|
||||
check (2, 3) notin dag
|
||||
dag.add( (2, 3) )
|
||||
check (2, 3) in dag
|
||||
dag.add(1->2)
|
||||
check (1->2) in dag
|
||||
check (2->3) notin dag
|
||||
dag.add(2->3)
|
||||
check (2->3) in dag
|
||||
|
||||
test "visits reachable vertices, nearest first":
|
||||
|
||||
|
@ -30,7 +30,7 @@ suite "Sorted DAG":
|
|||
# ②
|
||||
|
||||
var dag = SortedDag[int].new
|
||||
for edge in [ (0, 1), (1, 2), (0, 2) ]:
|
||||
for edge in [0->1, 1->2, 0->2]:
|
||||
dag.add(edge)
|
||||
|
||||
check toSeq(dag.visit(0)) == @[1, 2]
|
||||
|
@ -46,7 +46,7 @@ suite "Sorted DAG":
|
|||
# ③
|
||||
|
||||
var dag = SortedDag[int].new
|
||||
for edge in [ (5, 2), (5, 0), (4, 0), (4, 1), (2, 3), (3, 1) ]:
|
||||
for edge in [5->2, 5->0, 4->0, 4->1, 2->3, 3->1]:
|
||||
dag.add(edge)
|
||||
|
||||
let reachableFrom5 = toSeq(dag.visit(5))
|
||||
|
@ -65,11 +65,11 @@ suite "Sorted DAG":
|
|||
# gain ← spend
|
||||
|
||||
var dag = SortedDag[string].new
|
||||
for edge in [("acks", "ack1"),
|
||||
("acks", "ack2"),
|
||||
("ack1", "gain"),
|
||||
("ack2", "spend"),
|
||||
("spend", "gain")]:
|
||||
for edge in ["acks"->"ack1",
|
||||
"acks"->"ack2",
|
||||
"ack1"->"gain",
|
||||
"ack2"->"spend",
|
||||
"spend"->"gain"]:
|
||||
dag.add(edge)
|
||||
|
||||
let walk = toSeq dag.visit("acks")
|
||||
|
@ -91,28 +91,25 @@ suite "Sorted DAG":
|
|||
|
||||
var dag = SortedDag[int].new
|
||||
for vertex in [1,6]:
|
||||
dag.add((0, vertex))
|
||||
dag.add(0->vertex)
|
||||
for vertex in 1..<5:
|
||||
dag.add((vertex, vertex + 1))
|
||||
dag.add(vertex->vertex + 1)
|
||||
for vertex in 6..<10:
|
||||
dag.add((vertex, vertex + 1))
|
||||
dag.add(vertex->vertex + 1)
|
||||
for vertex in [1, 3, 5]:
|
||||
dag.add((vertex, vertex + 5))
|
||||
dag.add(vertex->vertex + 5)
|
||||
for vertex in [2, 4]:
|
||||
dag.add((vertex+5, vertex))
|
||||
dag.add(vertex+5->vertex)
|
||||
|
||||
check toSeq(dag.visit(0)) == @[1, 6, 7, 2, 3, 8, 9, 4, 5, 10]
|
||||
|
||||
test "handles DAGs with many edges":
|
||||
|
||||
var dag = SortedDag[int].new
|
||||
|
||||
var vertices: seq[int]
|
||||
|
||||
for _ in 0..10_000:
|
||||
let x, y = rand(100)
|
||||
if x != y:
|
||||
dag.add((min(x,y), max(x,y)))
|
||||
dag.add(min(x,y)->max(x,y))
|
||||
|
||||
var latest = -1
|
||||
for vertex in dag.visit(0):
|
||||
|
@ -125,7 +122,7 @@ suite "Sorted DAG":
|
|||
|
||||
var dag = SortedDag[int].new
|
||||
for i in 1..10_000:
|
||||
dag.add((i, i-1))
|
||||
dag.add(i->i-1)
|
||||
|
||||
var latest = 10_000
|
||||
for vertex in dag.visit(10_000):
|
||||
|
|
Loading…
Reference in New Issue