aboutsummaryrefslogtreecommitdiffstats
path: root/examples/routes.aup
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-10-04 13:58:19 +0100
committereunhhu <[email protected]>2026-10-04 13:58:19 +0100
commit7340ba9af757b6f135dff9c51a193ba527f061b3 (patch)
tree955bb163aa584d52cf402fb123c901ec2271939c /examples/routes.aup
parentfafed7edaf36ba18c200d395bd229d1f071cd409 (diff)
downloadaup-7340ba9af757b6f135dff9c51a193ba527f061b3.tar.gz
aup-7340ba9af757b6f135dff9c51a193ba527f061b3.zip
Count with for i in a .. b, break, nest fors and let an event's own lists (Pure 018)
Diffstat (limited to 'examples/routes.aup')
-rw-r--r--examples/routes.aup120
1 files changed, 120 insertions, 0 deletions
diff --git a/examples/routes.aup b/examples/routes.aup
new file mode 100644
index 0000000..6656947
--- /dev/null
+++ b/examples/routes.aup
@@ -0,0 +1,120 @@
+# Routes over a graph in one event each (Pure 018): breadth first, depth
+# first and the nearest by weight. A node's edges are a slice of the edges
+# list (keyed by from * 1048576 + to); the searches keep their queues and
+# what they have seen in the event's own lists, gone when it ends.
+record Node {
+ id = 0
+}
+record Edge {
+ link = 0
+ to = 0
+ w = 1
+}
+record Seen {
+ node = 0
+ depth = 0
+}
+record Step {
+ node = 0
+}
+record Pending {
+ rank = 0
+}
+state nodes: list of Node by id
+state edges: list of Edge by link
+state hops = -1
+state visited = 0
+state order = 0
+state shortest = -1
+input link = message {
+ from: u32
+ to: u32
+ w: u32
+}
+input route = message {
+ from: u32
+ to: u32
+}
+input walk = message {
+ from: u32
+}
+input path = message {
+ from: u32
+ to: u32
+}
+
+on link {
+ if !nodes.has(link.from) { nodes.add(Node { id: link.from }) }
+ if !nodes.has(link.to) { nodes.add(Node { id: link.to }) }
+ edges.add(Edge { link: link.from * 1048576 + link.to, to: link.to, w: link.w })
+}
+
+# Breadth first: the queue is read by position, every node enters it once.
+on route {
+ let seen: list of Seen by node
+ let queue: list of Step
+ queue.append(Step { node: route.from })
+ seen.add(Seen { node: route.from })
+ for i in 0 .. nodes.count {
+ if i >= queue.count { break }
+ let q = queue.first + i
+ for e in edges[q.node * 1048576 .. q.node * 1048576 + 1048576] {
+ if !seen.has(e.to) {
+ seen.add(Seen { node: e.to, depth: seen[q.node].depth + 1 })
+ queue.append(Step { node: e.to })
+ }
+ }
+ }
+ hops = if seen.has(route.to) { seen[route.to].depth } else { -1 }
+}
+
+# Depth first: a stack, each edge pushed once at most; depth is the order a node was reached in.
+on walk {
+ let seen: list of Seen by node
+ let stack: list of Step
+ stack.append(Step { node: walk.from })
+ let reached = 0
+ for i in 0 .. edges.count + 1 {
+ if stack.count == 0 { break }
+ let v = stack.last.node
+ stack.remove(stack.last)
+ if !seen.has(v) {
+ seen.add(Seen { node: v, depth: reached })
+ reached = reached + 1
+ for e in edges[v * 1048576 .. v * 1048576 + 1048576] {
+ if !seen.has(e.to) { stack.append(Step { node: e.to }) }
+ }
+ }
+ }
+ visited = seen.count
+ order = sum(s.depth * (s.node + 1) for s in seen)
+}
+
+# The nearest by weight (Dijkstra): pending ranks by dist * 1048576 + node, the nearest first.
+on path {
+ let best: list of Seen by node
+ let pending: list of Pending by rank
+ best.add(Seen { node: path.from })
+ pending.add(Pending { rank: path.from })
+ for i in 0 .. edges.count + 1 {
+ if pending.count == 0 { break }
+ let d = floor(pending.first.rank / 1048576)
+ let v = pending.first.rank - d * 1048576
+ pending.remove(pending.first)
+ if best[v].depth == d {
+ for e in edges[v * 1048576 .. v * 1048576 + 1048576] {
+ let far = d + e.w
+ if !best.has(e.to) {
+ best.add(Seen { node: e.to, depth: far })
+ pending.add(Pending { rank: far * 1048576 + e.to })
+ } else if far < best[e.to].depth {
+ best[e.to].depth = far
+ pending.add(Pending { rank: far * 1048576 + e.to })
+ }
+ }
+ }
+ }
+ shortest = if best.has(path.to) { best[path.to].depth } else { -1 }
+}
+
+view graph = "{nodes.count} nodes, {edges.count} edges"